locks: change POSIX lock ownership on execve when file_struct is displaced
Subsystems (3)
Jeff Layton
maintainerPATCH 1/1 locks: change POSIX lock ownership on execve when file_struct is displaced
From: Jeff Layton <[email protected]>
POSIX mandates that open fds and their associated file locks should be preserved across an execve. This works, unless the process is multithreaded at the time that execve is called.
In that case, we'll end up unsharing the files_struct but the locks will still have their fl_owner pointed at the old one. Eventually the last reference to the old files_struct is put and the locks get torn down.
The result is that all of your files will be intact with none of the locks you held before execve. The simple answer to this is "use OFD locks", but this is a nasty surprise and violates the spec.
On a successful execve, change ownership of any file_locks associated with the old files_struct to the new one, if we ended up swapping it out.
--- fs/exec.c | 4 +++- fs/file.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ fs/locks.c | 43 +++++++++++++++++++++++++++++++++++++++++++ include/linux/fdtable.h | 1 + include/linux/fs.h | 1 + 5 files changed, 92 insertions(+), 1 deletion(-)
fs/exec.c +3 -1
@@ -1812,8 +1812,10 @@ static int do_execveat_common(int fd, struct filename *filename,free_bprm (bprm);kfree (pathbuf);putname (filename); -if (displaced) +if (displaced) { +change_lock_owners (current->files, displaced);put_files_struct (displaced); + }return retval; out:
fs/file.c +44 -0
50 lines not on this page · raw message
fs/locks.c +43 -0
49 lines not on this page · raw message
include/linux/fdtable.h +1 -0
@@ -114,6 +114,7 @@ void do_close_on_exec(struct files_struct *);int iterate_fd (struct files_struct *,unsigned ,int (*)(const void *,struct file *,unsigned ),const void *); +void change_lock_owners (struct files_struct *,struct files_struct *);extern int __alloc_fd (struct files_struct *files,unsigned start,unsigned end,unsigned flags);
include/linux/fs.h +1 -0
@@ -1084,6 +1084,7 @@ extern void locks_remove_posix(struct file *, fl_owner_t);extern void locks_remove_file (struct file *);extern void locks_release_private (struct file_lock *);extern void posix_test_lock (struct file *,struct file_lock *); +extern void posix_chown_locks (struct file *,fl_owner_t old,fl_owner_t new);extern int posix_lock_file (struct file *,struct file_lock *,struct file_lock *);extern int posix_unblock_lock (struct file_lock *);extern int vfs_test_lock (struct file *,struct file_lock *);
Signature · 1 line
2.14.3