I have a vnode and I want to get the protection bits (sticky bit, write bit, etc.) of its associated file. I know I can get the vnode's vattr struct which contains a field called u_short va_mode; /* files access mode and type */.
However, I was wondering if this is the same thing as the vnode's associated file's mode_t st_mode; /* inode protection mode */. Does anybody know if these would be the same for a given vnode and its associated file?
My final goal is to see if a sticky bit is set for a vnode's assocated file.
The st_mode in struct stat is set from the vnode's va_mode, with the addition of a flag based on vnode type (eg VREG or VDIR). Take a look at http://fxr.watson.org/fxr/source/kern/vfs_vnops.c#L1428; that's the piece of code that fills in the struct stat.
Related
I am trying to extract libraries from the Dyld_shared_cache, and need to fix in external references.
For example, the pointers in the __DATA.__objc_selrefs section usually point to data outside the mach-o file, to fix that I would have to copy the corresponding c-string from the dyld and append it to the __TEXT.__objc_methname section.
Though from my understanding of the Mach-O file format, this extension of the __TEXT.__objc_methname would shift all the sections after it and would force me to fix all the offsets and pointers that reference them. Is there a way to add data to a section without breaking a lot of things?
Thanks!
Thanks to #Kamil.S for the idea about adding a new load command and section.
One way to achieve adding more data to a section is to create a duplicate segment and section and insert it before the __LINKEDIT segment.
Slide the __LINKEDIT segment so we have space to add the new section.
define the slide amount, this must be page-aligned, so I choose 0x4000.
add the slide amount to the relevant load commands, this includes but is not limited to:
__LINKEDIT segment (duh)
dyld_info_command
symtab_command
dysymtab_command
linkedit_data_commands
physically move the __LINKEDIT in the file.
duplicate the section and change the following1
size, should be the length of your new data.
addr, should be in the free space.
offset, should be in the free space.
duplicate the segment and change the following1
fileoff, should be the start of the free space.
vmaddr, should be the start of the free space.
filesize, anything as long as it is bigger than your data.
vmsize, must be identical to filesize.
nsects, change to reflect how many sections your adding.
cmdsize, change to reflect the size of the segment command and its section commands.
insert the duplicated segment and sections before the __LINKEDIT segment
update the mach_header
ncmds
sizeofcmds
physically write the extra data in the file.
you can optionally change the segname and sectname fields, though it isn't necessary. thanks Kamil.S!
UPDATE
After clarifing with OP that extension of __TEXT.__objc_methname would happen during Mach-O post processing of an existing executable I had a fresh look on the problem.
Another take would be to create a new load command LC_SEGMENT_64 with a new __TEXT_EXEC.__objc_methname segment / section entry (normally __TEXT_EXEC is used for some kernel stuff but essentially it's the same thing as __TEXT). Here's a quick POC to ilustrate the concept:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
#autoreleasepool {
printf("%lx",[NSObject new]);
}
return 0;
}
Compile like this:
gcc main.m -c -o main.o
ld main.o -rename_section __TEXT __objc_methname __TEXT_EXEC __objc_methname -lobjc -lc
Interestingly only ld up to High Sierra 10.14.6 generates __TEXT.__objc_methname, no trace of it on Catalina, it's done differently.
UPDATE2.
Playing around with it, I noticed execution rights for __TEXT segment (and __TEXT_EXEC for that matter) are not required for __objc_methname to work.
Even better specific segment & section names are not required:
I could pull off:
__DATA.__objc_methname
__DATA_CONST.__objc_methname
__ARBITRARY.__arbitrary
or in my case last __DATA section
__DATA.__objc_classrefs where the original the data got concatenated by the selector name.
It's all fine as long as a proper null terminated C-string with the selector name is there. If I intentionally break the "new\0" in hex editor or MachOView I'll get
"+[NSObject ne]: unrecognized selector sent to instance ..."
upon launching my POC executable so the value is used for sure.
So to sum __TEXT.__objc_methname section itself is likely some debugger hint made by the linker. The app runtime seems to only need selector names as char* anywhere in memory.
I'm doing this challenge thing and this is one of the levels:
An agent on Level 05 has told us about another big hack he's working on. Apparently someone broke into a popular shopping site, stole all the usernames and passwords and was going to post them online. Luckily, we got to them first and recovered the details. Why is this important? Well, it seems one of the Yakoottees was a member of that site.
He typically uses one of these three usernames: kazuya, kaz_whizz, kazuya99. We've put the recovered data on one of our servers. We've given you access, so see if you can find him on there. If we knew the password he uses maybe we can use that later.
Tip: The flag is his password.
I think I need to read this file called "182k_accounts_rip.txt". The directory is "/root/site_pwned" i think.
Maybe I need to read the file to get the password? The 'cat', 'less', 'more' and 'tail' command do not work. Maybe I need to see the current password with the user names mentioned? Please help
To read the file you can invoke vi or vim command from program using system function or execve family function as
int main(int argc, char *argv[]) {
system("vim 182k_accounts_rip.txt");
perror("system");
/* do the stuff here like use grep to find the pattern*/
return 0;
}
I am pulling data from a server and one of the folder name is longer than 256 bytes, so my CentOS is throwing an error that the name is too long. I have searched all over the internet but couldn't find any way to create a folder/file name with size of over 256 bytes under ext2/ext3/ext4 file systems.
However, One solution had suggested to create reiserfs file system alongside ext4 to handle files\folder with longer names. This solution might work, but I just read in one of the book that it is possible to extend the limit of filename size from 255 characters to 1012 characters if needed.
The maximal file name size is 255 characters. This limit could be extended to `1012` if needed.
Source: Google
But I couldn't find any website that explains how the filesystem could be modified to extend the size to 1012?
Can someone please help me with that?
Don't know where 1012 was found (mentioned in http://e2fsprogs.sourceforge.net/ext2intro.html - Design and Implementation of the Second Extended Filesystem, ISBN 90-367-0385-9. 1995), but in modern Linux kernel file name is fixed in struct ext2_dir_entry_2 with maximum of 255 chars (bytes):
https://elixir.bootlin.com/linux/v4.10/source/fs/ext2/ext2.h#L600
/*
* The new version of the directory entry. Since EXT2 structures are
* stored in intel byte order, and the name_len field could never be
* bigger than 255 chars, it's safe to reclaim the extra byte for the
* file_type field.
*/
struct ext2_dir_entry_2 {
__le32 inode; /* Inode number */
__le16 rec_len; /* Directory entry length */
__u8 name_len; /* Name length */
__u8 file_type;
char name[]; /* File name, up to EXT2_NAME_LEN */
};
There was struct ext2_dir_entry with longer file name length, but extra byte of name_len was redefined as file_type.
__le16 name_len; /* Name length */
So, current maximum file name length for ext2 is 255
https://elixir.bootlin.com/linux/v4.10/source/include/linux/ext2_fs.h#L22
#define EXT2_NAME_LEN 255
https://elixir.bootlin.com/linux/v4.10/source/fs/ext2/namei.c#L62
if (dentry->d_name.len > EXT2_NAME_LEN)
return ERR_PTR(-ENAMETOOLONG);
Same for ext3/ext4:
https://elixir.bootlin.com/linux/v4.10/source/fs/ext4/ext4.h#L1892
/*
* Structure of a directory entry
*/
#define EXT4_NAME_LEN 255
https://elixir.bootlin.com/linux/v4.10/source/fs/ext4/namei.c
* `len <= EXT4_NAME_LEN' is guaranteed by caller.
if (namelen > EXT4_NAME_LEN)
return NULL;
if (dentry->d_name.len > EXT4_NAME_LEN)
return ERR_PTR(-ENAMETOOLONG);
Ondisk format is described with 8 bit file_name too (file_type uses only 3 bits in older docs - EXT2_FT_MAX, but modern driver will not handle 255+ file names. ext4 has extra FT of 0xde):
http://www.nongnu.org/ext2-doc/ext2.html#IFDIR-NAME-LEN "4.1.3. name_len - 8bit unsigned value indicating how many bytes of character data are contained in the name."
http://cs.smith.edu/~nhowe/262/oldlabs/ext2.html#direntry "The file_type field indicates what kind of file the entry is referring to... The maximum length of a file name is EXT2_NAME_LEN, which is usually 255."
https://oss.oracle.com/projects/ocfs2/dist/documentation/disklayout.pdf#page=16 "__u8 name_len"
See https://en.wikipedia.org/wiki/Comparison_of_file_systems#Limits, not a lot of filesystems handle filenames of more than 255 bytes.
While it may not be a direct reply to your question, I do not think you should try to go this route (changing the maximum length).
From what server do you retrieve your files? Why not changing their name when doing the retrieval?
Are you sure that the whole path name is relevant, if you extract the first or last 250 characters isn't it enough to reference each file without ambiguity?
You have many options, depending on your constraints:
either generate "random" names (or sequential ones), and just store in a text file the mapping between old true name and the new fake name
or split the initial name in 250 characters path elements (or something like that) and create intermediate directories with them
You can find similar discussion at https://serverfault.com/questions/264339/how-to-increase-filename-size-limit-on-ext3-on-ubuntu
I'm reading the Understand the Linux Kernel book, and it says that the list of file_lock is stored in the file's inode (of field i_flock).
But in the sys_flock() of Linux 2.6.11.12, which will eventually call flock_lock_file(). It uses filp->f_dentry->d_inode->i_flock to get the list of file_lock and filp->f_dentry is an dentry of the directory which "contains" the file.
int flock_lock_file(struct file *filp, struct file_lock *new_fl) {
// ...
struct inode * inode = filp->f_dentry->d_inode;
// ...
}
Suppose that the file_lock list are linked with filp->f_dentry->d_inode->i_flock, What will happen when a hard link exists:
/some_path/foo/file.txt
/another_path/bar/file_link
and file_link is a hard link to file.txt
When we use this two path to open the same file, sys_open() will set filp->f_dentry to foo and bar separately, isn't it? If my guess is right, how file_lock can work?
The file_lock is indeed stored in the inode of the corresponding file.
An inode can be referred by several directory entries, which linked in inode's i_dentry field. Even for a unique file might have different filp->f_dentry, filp->f_dentry->d_inode is all refer to the same inode.
Please explain this statement:
directory_path=dentry_path_raw(lower_dentry,buf,buflen);
also give an example of how does it work
What fields does struct dentry contain?
What does the s_root field point to?
What does the field s_root contain?
You can check the fields of dentry here. dentry_path_raw puts the full path of the directory entry from the root of the file system into the buffer. s_root is a member of super block defined in linux/fs.h and is the root of the file system, which is a dentry.
char *dentry_path_raw(struct dentry *dentry, char *buf, int buflen)
The above function returns full pathname from root of the file system into the buffer.Each field is explained as below.
#dentry-dentry of a file to lookup
#buf-buffer to store path to
#buflen-length of #buf
For more detail check fs/dcache.c file.