diff options
author | Vitaliy Gusev <vgusev@openvz.org> | 2008-01-16 19:07:08 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2008-02-03 17:51:36 -0500 |
commit | ab1f16116527e42dec8aee176d673a41a881b809 (patch) | |
tree | 0d20fa10151e43f9f104986a2b89ec88ca0135af | |
parent | 4321e01e7dce8042758349ffa2929c723b0d4107 (diff) |
pid-namespaces-vs-locks-interaction
fcntl(F_GETLK,..) can return pid of process for not current pid namespace
(if process is belonged to the several namespaces). It is true also for
pids in /proc/locks. So correct behavior is saving pointer to the struct
pid of the process lock owner.
Signed-off-by: Vitaliy Gusev <vgusev@openvz.org>
Acked-by: Serge Hallyn <serue@us.ibm.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
-rw-r--r-- | fs/locks.c | 29 | ||||
-rw-r--r-- | include/linux/fs.h | 1 |
2 files changed, 24 insertions, 6 deletions
diff --git a/fs/locks.c b/fs/locks.c index faddccb6336a..49354b9c7dc1 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -125,6 +125,7 @@ | |||
125 | #include <linux/syscalls.h> | 125 | #include <linux/syscalls.h> |
126 | #include <linux/time.h> | 126 | #include <linux/time.h> |
127 | #include <linux/rcupdate.h> | 127 | #include <linux/rcupdate.h> |
128 | #include <linux/pid_namespace.h> | ||
128 | 129 | ||
129 | #include <asm/semaphore.h> | 130 | #include <asm/semaphore.h> |
130 | #include <asm/uaccess.h> | 131 | #include <asm/uaccess.h> |
@@ -185,6 +186,7 @@ void locks_init_lock(struct file_lock *fl) | |||
185 | fl->fl_fasync = NULL; | 186 | fl->fl_fasync = NULL; |
186 | fl->fl_owner = NULL; | 187 | fl->fl_owner = NULL; |
187 | fl->fl_pid = 0; | 188 | fl->fl_pid = 0; |
189 | fl->fl_nspid = NULL; | ||
188 | fl->fl_file = NULL; | 190 | fl->fl_file = NULL; |
189 | fl->fl_flags = 0; | 191 | fl->fl_flags = 0; |
190 | fl->fl_type = 0; | 192 | fl->fl_type = 0; |
@@ -553,6 +555,8 @@ static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl) | |||
553 | { | 555 | { |
554 | list_add(&fl->fl_link, &file_lock_list); | 556 | list_add(&fl->fl_link, &file_lock_list); |
555 | 557 | ||
558 | fl->fl_nspid = get_pid(task_tgid(current)); | ||
559 | |||
556 | /* insert into file's list */ | 560 | /* insert into file's list */ |
557 | fl->fl_next = *pos; | 561 | fl->fl_next = *pos; |
558 | *pos = fl; | 562 | *pos = fl; |
@@ -584,6 +588,11 @@ static void locks_delete_lock(struct file_lock **thisfl_p) | |||
584 | if (fl->fl_ops && fl->fl_ops->fl_remove) | 588 | if (fl->fl_ops && fl->fl_ops->fl_remove) |
585 | fl->fl_ops->fl_remove(fl); | 589 | fl->fl_ops->fl_remove(fl); |
586 | 590 | ||
591 | if (fl->fl_nspid) { | ||
592 | put_pid(fl->fl_nspid); | ||
593 | fl->fl_nspid = NULL; | ||
594 | } | ||
595 | |||
587 | locks_wake_up_blocks(fl); | 596 | locks_wake_up_blocks(fl); |
588 | locks_free_lock(fl); | 597 | locks_free_lock(fl); |
589 | } | 598 | } |
@@ -646,14 +655,16 @@ posix_test_lock(struct file *filp, struct file_lock *fl) | |||
646 | if (posix_locks_conflict(fl, cfl)) | 655 | if (posix_locks_conflict(fl, cfl)) |
647 | break; | 656 | break; |
648 | } | 657 | } |
649 | if (cfl) | 658 | if (cfl) { |
650 | __locks_copy_lock(fl, cfl); | 659 | __locks_copy_lock(fl, cfl); |
651 | else | 660 | if (cfl->fl_nspid) |
661 | fl->fl_pid = pid_nr_ns(cfl->fl_nspid, | ||
662 | task_active_pid_ns(current)); | ||
663 | } else | ||
652 | fl->fl_type = F_UNLCK; | 664 | fl->fl_type = F_UNLCK; |
653 | unlock_kernel(); | 665 | unlock_kernel(); |
654 | return; | 666 | return; |
655 | } | 667 | } |
656 | |||
657 | EXPORT_SYMBOL(posix_test_lock); | 668 | EXPORT_SYMBOL(posix_test_lock); |
658 | 669 | ||
659 | /* | 670 | /* |
@@ -2070,6 +2081,12 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl, | |||
2070 | int id, char *pfx) | 2081 | int id, char *pfx) |
2071 | { | 2082 | { |
2072 | struct inode *inode = NULL; | 2083 | struct inode *inode = NULL; |
2084 | unsigned int fl_pid; | ||
2085 | |||
2086 | if (fl->fl_nspid) | ||
2087 | fl_pid = pid_nr_ns(fl->fl_nspid, task_active_pid_ns(current)); | ||
2088 | else | ||
2089 | fl_pid = fl->fl_pid; | ||
2073 | 2090 | ||
2074 | if (fl->fl_file != NULL) | 2091 | if (fl->fl_file != NULL) |
2075 | inode = fl->fl_file->f_path.dentry->d_inode; | 2092 | inode = fl->fl_file->f_path.dentry->d_inode; |
@@ -2110,16 +2127,16 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl, | |||
2110 | } | 2127 | } |
2111 | if (inode) { | 2128 | if (inode) { |
2112 | #ifdef WE_CAN_BREAK_LSLK_NOW | 2129 | #ifdef WE_CAN_BREAK_LSLK_NOW |
2113 | seq_printf(f, "%d %s:%ld ", fl->fl_pid, | 2130 | seq_printf(f, "%d %s:%ld ", fl_pid, |
2114 | inode->i_sb->s_id, inode->i_ino); | 2131 | inode->i_sb->s_id, inode->i_ino); |
2115 | #else | 2132 | #else |
2116 | /* userspace relies on this representation of dev_t ;-( */ | 2133 | /* userspace relies on this representation of dev_t ;-( */ |
2117 | seq_printf(f, "%d %02x:%02x:%ld ", fl->fl_pid, | 2134 | seq_printf(f, "%d %02x:%02x:%ld ", fl_pid, |
2118 | MAJOR(inode->i_sb->s_dev), | 2135 | MAJOR(inode->i_sb->s_dev), |
2119 | MINOR(inode->i_sb->s_dev), inode->i_ino); | 2136 | MINOR(inode->i_sb->s_dev), inode->i_ino); |
2120 | #endif | 2137 | #endif |
2121 | } else { | 2138 | } else { |
2122 | seq_printf(f, "%d <none>:0 ", fl->fl_pid); | 2139 | seq_printf(f, "%d <none>:0 ", fl_pid); |
2123 | } | 2140 | } |
2124 | if (IS_POSIX(fl)) { | 2141 | if (IS_POSIX(fl)) { |
2125 | if (fl->fl_end == OFFSET_MAX) | 2142 | if (fl->fl_end == OFFSET_MAX) |
diff --git a/include/linux/fs.h b/include/linux/fs.h index a516b6716870..b7736ab8bb5e 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -872,6 +872,7 @@ struct file_lock { | |||
872 | struct list_head fl_block; /* circular list of blocked processes */ | 872 | struct list_head fl_block; /* circular list of blocked processes */ |
873 | fl_owner_t fl_owner; | 873 | fl_owner_t fl_owner; |
874 | unsigned int fl_pid; | 874 | unsigned int fl_pid; |
875 | struct pid *fl_nspid; | ||
875 | wait_queue_head_t fl_wait; | 876 | wait_queue_head_t fl_wait; |
876 | struct file *fl_file; | 877 | struct file *fl_file; |
877 | unsigned char fl_flags; | 878 | unsigned char fl_flags; |