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>
diff --git a/fs/locks.c b/fs/locks.c
index faddccb..49354b9 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -125,6 +125,7 @@
#include <linux/syscalls.h>
#include <linux/time.h>
#include <linux/rcupdate.h>
+#include <linux/pid_namespace.h>
#include <asm/semaphore.h>
#include <asm/uaccess.h>
@@ -185,6 +186,7 @@
fl->fl_fasync = NULL;
fl->fl_owner = NULL;
fl->fl_pid = 0;
+ fl->fl_nspid = NULL;
fl->fl_file = NULL;
fl->fl_flags = 0;
fl->fl_type = 0;
@@ -553,6 +555,8 @@
{
list_add(&fl->fl_link, &file_lock_list);
+ fl->fl_nspid = get_pid(task_tgid(current));
+
/* insert into file's list */
fl->fl_next = *pos;
*pos = fl;
@@ -584,6 +588,11 @@
if (fl->fl_ops && fl->fl_ops->fl_remove)
fl->fl_ops->fl_remove(fl);
+ if (fl->fl_nspid) {
+ put_pid(fl->fl_nspid);
+ fl->fl_nspid = NULL;
+ }
+
locks_wake_up_blocks(fl);
locks_free_lock(fl);
}
@@ -646,14 +655,16 @@
if (posix_locks_conflict(fl, cfl))
break;
}
- if (cfl)
+ if (cfl) {
__locks_copy_lock(fl, cfl);
- else
+ if (cfl->fl_nspid)
+ fl->fl_pid = pid_nr_ns(cfl->fl_nspid,
+ task_active_pid_ns(current));
+ } else
fl->fl_type = F_UNLCK;
unlock_kernel();
return;
}
-
EXPORT_SYMBOL(posix_test_lock);
/*
@@ -2070,6 +2081,12 @@
int id, char *pfx)
{
struct inode *inode = NULL;
+ unsigned int fl_pid;
+
+ if (fl->fl_nspid)
+ fl_pid = pid_nr_ns(fl->fl_nspid, task_active_pid_ns(current));
+ else
+ fl_pid = fl->fl_pid;
if (fl->fl_file != NULL)
inode = fl->fl_file->f_path.dentry->d_inode;
@@ -2110,16 +2127,16 @@
}
if (inode) {
#ifdef WE_CAN_BREAK_LSLK_NOW
- seq_printf(f, "%d %s:%ld ", fl->fl_pid,
+ seq_printf(f, "%d %s:%ld ", fl_pid,
inode->i_sb->s_id, inode->i_ino);
#else
/* userspace relies on this representation of dev_t ;-( */
- seq_printf(f, "%d %02x:%02x:%ld ", fl->fl_pid,
+ seq_printf(f, "%d %02x:%02x:%ld ", fl_pid,
MAJOR(inode->i_sb->s_dev),
MINOR(inode->i_sb->s_dev), inode->i_ino);
#endif
} else {
- seq_printf(f, "%d <none>:0 ", fl->fl_pid);
+ seq_printf(f, "%d <none>:0 ", fl_pid);
}
if (IS_POSIX(fl)) {
if (fl->fl_end == OFFSET_MAX)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index a516b67..b7736ab 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -872,6 +872,7 @@
struct list_head fl_block; /* circular list of blocked processes */
fl_owner_t fl_owner;
unsigned int fl_pid;
+ struct pid *fl_nspid;
wait_queue_head_t fl_wait;
struct file *fl_file;
unsigned char fl_flags;