In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-01 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)05/31 Report--
This article mainly introduces the relevant knowledge of "how to solve the synchronization problem of linux executable file and write operation". The editor shows you the operation process through an actual case. The operation method is simple and fast, and it is practical. I hope this article "how to solve the synchronization problem of linux executable file and write operation" can help you solve the problem.
The inode node contains a data item called i_writecount, which is obviously used to record the number of files written, for synchronization, and its type is also atomic_t. There are two functions we need to know about write operations in the kernel, which are:
The copy code is as follows:
Int get_write_access (struct inode * inode)
{
Spin_lock (& inode- > i_lock)
If (& inode- > i_writecount)
< 0) { spin_unlock(&inode->I_lock)
Return-etxtbsy
}
Atomic_inc (& inode- > i_writecount)
Spin_unlock (& inode- > i_lock)
Return 0
}
Int deny_write_access (struct file * file)
{
Struct inode * inode = file- > fancipath.dentry-> d_inode
Spin_lock (& inode- > i_lock)
If (atomic_read (& inode- > i_writecount) > 0) {/ / failure is returned if the file is opened
Spin_unlock (& inode- > i_lock)
Return-etxtbsy
}
Atomic_dec (& inode- > i_writecount)
Spin_unlock (& inode- > i_lock)
}
Both functions are simple, and the get_write_acess function is the same as the name, and so is deny_write_access. If a file is executed and ensures that it cannot be written during execution, deny_write_access should be called to turn off write permissions before starting execution. Then check to see if the execve system call has done so.
Call do_execve in sys_execve, and then call the function open_exec. Take a look at the code of open_exec:
The copy code is as follows:
Struct file * open_exec (const char * name)
{
Struct file * file
Int err
File = do_filp_open (at_fdcwd, name
O_largefile | o_rdonly | fmode_exec, 0
May_exec | may_open)
If (is_err (file))
Goto out
Err =-eacces
If (! s_isreg (file- > fancipath.dentry-> diciinode-> i_mode))
Goto exit
If (file- > fancipath.mnt-> mnt_flags & mnt_noexec)
Goto exit
Fsnotify_open (file- > f_path.dentry)
Err = deny_write_access (file); / / call
If (err)
Goto exit
Out:
Return file
Exit:
Fput (file)
Return err_ptr (err)
}
You can clearly see the call to deny_write_access, exactly as expected. In the call to open, there should be a call to get_write_access. The call to this function is included in the _ _ dentry_open function associated with the open call.
The copy code is as follows:
If (f-> f_mode & fmode_write) {
Error = _ _ get_file_write_access (inode, mnt)
If (error)
Goto cleanup_file
If (! special_file (inode- > i_mode))
File_take_write (f)
}
The _ _ get_file_write_access (inode, mnt) encapsulates get_write_access.
So how does the kernel ensure that a file being written is not allowed to be executed? This is also very simple. When a file is already open for write, the i_writecount of its corresponding inode will become 1, so when executing execve, it will also call deny_write_access to read i_writecount > 0 and return a failure, so execve will also return a failure.
Here is the scenario where writing files is related to i_writecount:
When writing and opening a file, in the function dentry_open:
The copy code is as follows:
If (f-> f_mode & fmode_write) {
Error = get_write_access (inode)
If (error)
Goto cleanup_file
}
Of course, when the file is closed, the code will be executed:
The copy code is as follows:
If (file- > f_mode & fmode_write)
Put_write_access (inode)
The put_write_access code is simple:
The copy code is as follows:
Static inline void put_write_access (struct inode * inode)
{
Atomic_dec (& inode- > i_writecount)
}
So I wrote a simple code, an empty loop, when the file is executed, in bash, echo > > executable file, the result is expected, return failure, and prompt the message text file busy.
Then whether this mechanism is also applicable to the mapping mechanism, when executing the executable file, it will mmap some associated dynamic link libraries, whether these dynamic link libraries are not allowed to be written after mmap and mmap is not allowed when writing? This needs to be considered because it is related to security. Because library files are also executable code, tampering can also cause security problems.
Mmap has a related check in the function that calls mmap_region:
The copy code is as follows:
If (vm_flags & vm_denywrite) {
Error = deny_write_access (file)
If (error)
Goto free_vma
Correct_wcount = 1
}
Where the flags parameter in the mmap call is correctly assigned to vm_flags, and the corresponding relation is that map_denywrire is set, then vm_denywrite is also set. Here is a simple code to test it:
The copy code is as follows:
# include
# include
# include
# include
# include
# include
Int main ()
{
Int fd
Void * src = null
Fd = open ("test.txt", o_rdonly)
If (fd! = 0)
{
If ((src = mmap (0recom 5je protagonist read | prot_exec, map_private | map_denywrite,fd,0)) = = map_failed)
{
Printf ("mmap error\ n")
Printf ("% s\ n", strerror (errno))
} else {
Printf ("% x\ n", src)
}
}
File * fd_t = fopen ("test.txt", "w")
If (! fd_t)
{
Printf ("open for write error\ n")
Printf ("% s\ n", strerror (errno))
Return 0
}
If (fwrite ("0000", sizeof (char), 4 FD é t)! = 4)
{
Printf ("fwrite error\ n")
}
Fclose (fd_t)
Close (fd)
Return 1
}
The last test.txt is written as "0000". Strangely, it seems that map_dentwrite doesn't work. So man mmap looked at it and found:
Map_denywrite
This flag is ignored. (long ago, it signaled that attempts to write to the underlying file should fail with etxtbusy. But this was a source of denial-of-service attacks.)
It turns out that this logo no longer works at the user level, and it also explains the reason, which is easy to cause denial of service attacks. Attackers maliciously map files to be written by some system programs in map_denywrite mode, which will cause normal programs to fail to write files. However, vm_denywrite is still used in the kernel, there is still a call to deny_write_access in mmap, but the call to it is no longer driven by the map_denywrite of the flag parameter in mmap.
This is the end of the content on "how to solve the synchronization problem of linux executable files and write operations". Thank you for your reading. If you want to know more about the industry, you can follow the industry information channel. The editor will update different knowledge points for you every day.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.