aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2018-03-23 01:22:05 -0400
committerEric W. Biederman <ebiederm@xmission.com>2018-03-24 12:25:37 -0400
commit03f1fc09180b345582889a344b012d069b3a6dbe (patch)
treedcf320097f15d377f9a3c3f51d8bf92e26762f94
parentf83a396d06d499029fe6d32e326605a2b5ca4eff (diff)
ipc/util: Helpers for making the sysvipc operations pid namespace aware
Capture the pid namespace when /proc/sysvipc/msg /proc/sysvipc/shm and /proc/sysvipc/sem are opened, and make it available through the new helper ipc_seq_pid_ns. This makes it possible to report the pids in these files in the pid namespace of the opener of the files. Implement ipc_update_pid. A simple impline helper that will only update a struct pid pointer if the new value does not equal the old value. This removes the need for wordy code sequences like: old = object->pid; object->pid = new; put_pid(old); and old = object->pid; if (old != new) { object->pid = new; put_pid(old); } Allowing the following to be written instead: ipc_update_pid(&object->pid, new); Which is easier to read and ensures that the pid reference count is not touched the old and the new values are the same. Not touching the reference count in this case is important to help avoid issues like af_unix experienced, where multiple threads of the same process managed to bounce the struct pid between cpu cache lines, but updating the pids reference count. Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
-rw-r--r--ipc/util.c9
-rw-r--r--ipc/util.h11
2 files changed, 20 insertions, 0 deletions
diff --git a/ipc/util.c b/ipc/util.c
index 4ed5a17dd06f..3783b7991cc7 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -747,9 +747,16 @@ int ipc_parse_version(int *cmd)
747#ifdef CONFIG_PROC_FS 747#ifdef CONFIG_PROC_FS
748struct ipc_proc_iter { 748struct ipc_proc_iter {
749 struct ipc_namespace *ns; 749 struct ipc_namespace *ns;
750 struct pid_namespace *pid_ns;
750 struct ipc_proc_iface *iface; 751 struct ipc_proc_iface *iface;
751}; 752};
752 753
754struct pid_namespace *ipc_seq_pid_ns(struct seq_file *s)
755{
756 struct ipc_proc_iter *iter = s->private;
757 return iter->pid_ns;
758}
759
753/* 760/*
754 * This routine locks the ipc structure found at least at position pos. 761 * This routine locks the ipc structure found at least at position pos.
755 */ 762 */
@@ -872,6 +879,7 @@ static int sysvipc_proc_open(struct inode *inode, struct file *file)
872 879
873 iter->iface = PDE_DATA(inode); 880 iter->iface = PDE_DATA(inode);
874 iter->ns = get_ipc_ns(current->nsproxy->ipc_ns); 881 iter->ns = get_ipc_ns(current->nsproxy->ipc_ns);
882 iter->pid_ns = get_pid_ns(task_active_pid_ns(current));
875 883
876 return 0; 884 return 0;
877} 885}
@@ -881,6 +889,7 @@ static int sysvipc_proc_release(struct inode *inode, struct file *file)
881 struct seq_file *seq = file->private_data; 889 struct seq_file *seq = file->private_data;
882 struct ipc_proc_iter *iter = seq->private; 890 struct ipc_proc_iter *iter = seq->private;
883 put_ipc_ns(iter->ns); 891 put_ipc_ns(iter->ns);
892 put_pid_ns(iter->pid_ns);
884 return seq_release_private(inode, file); 893 return seq_release_private(inode, file);
885} 894}
886 895
diff --git a/ipc/util.h b/ipc/util.h
index 959c10eb9cc1..e39ed9705f99 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -23,6 +23,7 @@ int msg_init(void);
23void shm_init(void); 23void shm_init(void);
24 24
25struct ipc_namespace; 25struct ipc_namespace;
26struct pid_namespace;
26 27
27#ifdef CONFIG_POSIX_MQUEUE 28#ifdef CONFIG_POSIX_MQUEUE
28extern void mq_clear_sbinfo(struct ipc_namespace *ns); 29extern void mq_clear_sbinfo(struct ipc_namespace *ns);
@@ -86,6 +87,7 @@ int ipc_init_ids(struct ipc_ids *);
86#ifdef CONFIG_PROC_FS 87#ifdef CONFIG_PROC_FS
87void __init ipc_init_proc_interface(const char *path, const char *header, 88void __init ipc_init_proc_interface(const char *path, const char *header,
88 int ids, int (*show)(struct seq_file *, void *)); 89 int ids, int (*show)(struct seq_file *, void *));
90struct pid_namespace *ipc_seq_pid_ns(struct seq_file *);
89#else 91#else
90#define ipc_init_proc_interface(path, header, ids, show) do {} while (0) 92#define ipc_init_proc_interface(path, header, ids, show) do {} while (0)
91#endif 93#endif
@@ -150,6 +152,15 @@ struct kern_ipc_perm *ipcctl_pre_down_nolock(struct ipc_namespace *ns,
150 struct ipc_ids *ids, int id, int cmd, 152 struct ipc_ids *ids, int id, int cmd,
151 struct ipc64_perm *perm, int extra_perm); 153 struct ipc64_perm *perm, int extra_perm);
152 154
155static inline void ipc_update_pid(struct pid **pos, struct pid *pid)
156{
157 struct pid *old = *pos;
158 if (old != pid) {
159 *pos = get_pid(pid);
160 put_pid(old);
161 }
162}
163
153#ifndef CONFIG_ARCH_WANT_IPC_PARSE_VERSION 164#ifndef CONFIG_ARCH_WANT_IPC_PARSE_VERSION
154/* On IA-64, we always use the "64-bit version" of the IPC structures. */ 165/* On IA-64, we always use the "64-bit version" of the IPC structures. */
155# define ipc_parse_version(cmd) IPC_64 166# define ipc_parse_version(cmd) IPC_64