aboutsummaryrefslogtreecommitdiffstats
path: root/fs/autofs4
diff options
context:
space:
mode:
authorSukadev Bhattiprolu <sukadev@us.ibm.com>2014-01-23 18:54:57 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-01-23 19:36:58 -0500
commit6eaba35b437438988078efc92f1ef445a00cd7bc (patch)
tree7fcd78f3c0c8423a87464561d410784d7389f944 /fs/autofs4
parent499a4584d7f817d43d09ccfc6bb26315eeaab6bc (diff)
autofs4: allow autofs to work outside the initial PID namespace
Enable autofs4 to work in a "container". oz_pgrp is converted from pid_t to struct pid and this is stored at mount time based on the "pgrp=" option or if the option is missing then the current pgrp. The "pgrp=" option is interpreted in the PID namespace of the current process. This option is flawed in that it doesn't carry the namespace information, so it should be deprecated. AFAICS the autofs daemon always sends the current pgrp, which is the default anyway. The oz_pgrp is also set from the AUTOFS_DEV_IOCTL_SETPIPEFD_CMD ioctl. This ioctl sets oz_pgrp to the current pgrp. It is not allowed to change the pid namespace. oz_pgrp is used mainly to determine whether the process traversing the autofs mount tree is the autofs daemon itself or not. This function now compares the pid pointers instead of the pid_t values. One other use of oz_pgrp is in autofs4_show_options. There is shows the virtual pid number (i.e. the one that is valid inside the PID namespace of the calling process) For debugging printk convert oz_pgrp to the value in the initial pid namespace. Signed-off-by: Sukadev Bhattiprolu <sukadev@us.ibm.com> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Acked-by: Serge Hallyn <serge.hallyn@canonical.com> Cc: Eric Biederman <ebiederm@xmission.com> Acked-by: Ian Kent <raven@themaw.net> Cc: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/autofs4')
-rw-r--r--fs/autofs4/autofs_i.h4
-rw-r--r--fs/autofs4/dev-ioctl.c16
-rw-r--r--fs/autofs4/inode.c36
3 files changed, 43 insertions, 13 deletions
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index 4218e26df916..acf32054edd8 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -104,7 +104,7 @@ struct autofs_sb_info {
104 u32 magic; 104 u32 magic;
105 int pipefd; 105 int pipefd;
106 struct file *pipe; 106 struct file *pipe;
107 pid_t oz_pgrp; 107 struct pid *oz_pgrp;
108 int catatonic; 108 int catatonic;
109 int version; 109 int version;
110 int sub_version; 110 int sub_version;
@@ -140,7 +140,7 @@ static inline struct autofs_info *autofs4_dentry_ino(struct dentry *dentry)
140 filesystem without "magic".) */ 140 filesystem without "magic".) */
141 141
142static inline int autofs4_oz_mode(struct autofs_sb_info *sbi) { 142static inline int autofs4_oz_mode(struct autofs_sb_info *sbi) {
143 return sbi->catatonic || task_pgrp_nr(current) == sbi->oz_pgrp; 143 return sbi->catatonic || task_pgrp(current) == sbi->oz_pgrp;
144} 144}
145 145
146/* Does a dentry have some pending activity? */ 146/* Does a dentry have some pending activity? */
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c
index 1818ce7f5a06..3182c0e68b42 100644
--- a/fs/autofs4/dev-ioctl.c
+++ b/fs/autofs4/dev-ioctl.c
@@ -346,6 +346,7 @@ static int autofs_dev_ioctl_setpipefd(struct file *fp,
346{ 346{
347 int pipefd; 347 int pipefd;
348 int err = 0; 348 int err = 0;
349 struct pid *new_pid = NULL;
349 350
350 if (param->setpipefd.pipefd == -1) 351 if (param->setpipefd.pipefd == -1)
351 return -EINVAL; 352 return -EINVAL;
@@ -357,7 +358,17 @@ static int autofs_dev_ioctl_setpipefd(struct file *fp,
357 mutex_unlock(&sbi->wq_mutex); 358 mutex_unlock(&sbi->wq_mutex);
358 return -EBUSY; 359 return -EBUSY;
359 } else { 360 } else {
360 struct file *pipe = fget(pipefd); 361 struct file *pipe;
362
363 new_pid = get_task_pid(current, PIDTYPE_PGID);
364
365 if (ns_of_pid(new_pid) != ns_of_pid(sbi->oz_pgrp)) {
366 AUTOFS_WARN("Not allowed to change PID namespace");
367 err = -EINVAL;
368 goto out;
369 }
370
371 pipe = fget(pipefd);
361 if (!pipe) { 372 if (!pipe) {
362 err = -EBADF; 373 err = -EBADF;
363 goto out; 374 goto out;
@@ -367,12 +378,13 @@ static int autofs_dev_ioctl_setpipefd(struct file *fp,
367 fput(pipe); 378 fput(pipe);
368 goto out; 379 goto out;
369 } 380 }
370 sbi->oz_pgrp = task_pgrp_nr(current); 381 swap(sbi->oz_pgrp, new_pid);
371 sbi->pipefd = pipefd; 382 sbi->pipefd = pipefd;
372 sbi->pipe = pipe; 383 sbi->pipe = pipe;
373 sbi->catatonic = 0; 384 sbi->catatonic = 0;
374 } 385 }
375out: 386out:
387 put_pid(new_pid);
376 mutex_unlock(&sbi->wq_mutex); 388 mutex_unlock(&sbi->wq_mutex);
377 return err; 389 return err;
378} 390}
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index 3b9cc9b973c2..a3de082db620 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -56,8 +56,11 @@ void autofs4_kill_sb(struct super_block *sb)
56 * just call kill_anon_super when we are called from 56 * just call kill_anon_super when we are called from
57 * deactivate_super. 57 * deactivate_super.
58 */ 58 */
59 if (sbi) /* Free wait queues, close pipe */ 59 if (sbi) {
60 /* Free wait queues, close pipe */
60 autofs4_catatonic_mode(sbi); 61 autofs4_catatonic_mode(sbi);
62 put_pid(sbi->oz_pgrp);
63 }
61 64
62 DPRINTK("shutting down"); 65 DPRINTK("shutting down");
63 kill_litter_super(sb); 66 kill_litter_super(sb);
@@ -80,7 +83,7 @@ static int autofs4_show_options(struct seq_file *m, struct dentry *root)
80 if (!gid_eq(root_inode->i_gid, GLOBAL_ROOT_GID)) 83 if (!gid_eq(root_inode->i_gid, GLOBAL_ROOT_GID))
81 seq_printf(m, ",gid=%u", 84 seq_printf(m, ",gid=%u",
82 from_kgid_munged(&init_user_ns, root_inode->i_gid)); 85 from_kgid_munged(&init_user_ns, root_inode->i_gid));
83 seq_printf(m, ",pgrp=%d", sbi->oz_pgrp); 86 seq_printf(m, ",pgrp=%d", pid_vnr(sbi->oz_pgrp));
84 seq_printf(m, ",timeout=%lu", sbi->exp_timeout/HZ); 87 seq_printf(m, ",timeout=%lu", sbi->exp_timeout/HZ);
85 seq_printf(m, ",minproto=%d", sbi->min_proto); 88 seq_printf(m, ",minproto=%d", sbi->min_proto);
86 seq_printf(m, ",maxproto=%d", sbi->max_proto); 89 seq_printf(m, ",maxproto=%d", sbi->max_proto);
@@ -124,7 +127,8 @@ static const match_table_t tokens = {
124}; 127};
125 128
126static int parse_options(char *options, int *pipefd, kuid_t *uid, kgid_t *gid, 129static int parse_options(char *options, int *pipefd, kuid_t *uid, kgid_t *gid,
127 pid_t *pgrp, unsigned int *type, int *minproto, int *maxproto) 130 int *pgrp, bool *pgrp_set, unsigned int *type,
131 int *minproto, int *maxproto)
128{ 132{
129 char *p; 133 char *p;
130 substring_t args[MAX_OPT_ARGS]; 134 substring_t args[MAX_OPT_ARGS];
@@ -132,7 +136,6 @@ static int parse_options(char *options, int *pipefd, kuid_t *uid, kgid_t *gid,
132 136
133 *uid = current_uid(); 137 *uid = current_uid();
134 *gid = current_gid(); 138 *gid = current_gid();
135 *pgrp = task_pgrp_nr(current);
136 139
137 *minproto = AUTOFS_MIN_PROTO_VERSION; 140 *minproto = AUTOFS_MIN_PROTO_VERSION;
138 *maxproto = AUTOFS_MAX_PROTO_VERSION; 141 *maxproto = AUTOFS_MAX_PROTO_VERSION;
@@ -171,6 +174,7 @@ static int parse_options(char *options, int *pipefd, kuid_t *uid, kgid_t *gid,
171 if (match_int(args, &option)) 174 if (match_int(args, &option))
172 return 1; 175 return 1;
173 *pgrp = option; 176 *pgrp = option;
177 *pgrp_set = true;
174 break; 178 break;
175 case Opt_minproto: 179 case Opt_minproto:
176 if (match_int(args, &option)) 180 if (match_int(args, &option))
@@ -206,6 +210,8 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
206 int pipefd; 210 int pipefd;
207 struct autofs_sb_info *sbi; 211 struct autofs_sb_info *sbi;
208 struct autofs_info *ino; 212 struct autofs_info *ino;
213 int pgrp;
214 bool pgrp_set = false;
209 215
210 sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); 216 sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
211 if (!sbi) 217 if (!sbi)
@@ -218,7 +224,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
218 sbi->pipe = NULL; 224 sbi->pipe = NULL;
219 sbi->catatonic = 1; 225 sbi->catatonic = 1;
220 sbi->exp_timeout = 0; 226 sbi->exp_timeout = 0;
221 sbi->oz_pgrp = task_pgrp_nr(current); 227 sbi->oz_pgrp = NULL;
222 sbi->sb = s; 228 sbi->sb = s;
223 sbi->version = 0; 229 sbi->version = 0;
224 sbi->sub_version = 0; 230 sbi->sub_version = 0;
@@ -255,12 +261,23 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
255 261
256 /* Can this call block? */ 262 /* Can this call block? */
257 if (parse_options(data, &pipefd, &root_inode->i_uid, &root_inode->i_gid, 263 if (parse_options(data, &pipefd, &root_inode->i_uid, &root_inode->i_gid,
258 &sbi->oz_pgrp, &sbi->type, &sbi->min_proto, 264 &pgrp, &pgrp_set, &sbi->type, &sbi->min_proto,
259 &sbi->max_proto)) { 265 &sbi->max_proto)) {
260 printk("autofs: called with bogus options\n"); 266 printk("autofs: called with bogus options\n");
261 goto fail_dput; 267 goto fail_dput;
262 } 268 }
263 269
270 if (pgrp_set) {
271 sbi->oz_pgrp = find_get_pid(pgrp);
272 if (!sbi->oz_pgrp) {
273 pr_warn("autofs: could not find process group %d\n",
274 pgrp);
275 goto fail_dput;
276 }
277 } else {
278 sbi->oz_pgrp = get_task_pid(current, PIDTYPE_PGID);
279 }
280
264 if (autofs_type_trigger(sbi->type)) 281 if (autofs_type_trigger(sbi->type))
265 __managed_dentry_set_managed(root); 282 __managed_dentry_set_managed(root);
266 283
@@ -284,9 +301,9 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
284 sbi->version = sbi->max_proto; 301 sbi->version = sbi->max_proto;
285 sbi->sub_version = AUTOFS_PROTO_SUBVERSION; 302 sbi->sub_version = AUTOFS_PROTO_SUBVERSION;
286 303
287 DPRINTK("pipe fd = %d, pgrp = %u", pipefd, sbi->oz_pgrp); 304 DPRINTK("pipe fd = %d, pgrp = %u", pipefd, pid_nr(sbi->oz_pgrp));
288 pipe = fget(pipefd); 305 pipe = fget(pipefd);
289 306
290 if (!pipe) { 307 if (!pipe) {
291 printk("autofs: could not open pipe file descriptor\n"); 308 printk("autofs: could not open pipe file descriptor\n");
292 goto fail_dput; 309 goto fail_dput;
@@ -316,6 +333,7 @@ fail_dput:
316fail_ino: 333fail_ino:
317 kfree(ino); 334 kfree(ino);
318fail_free: 335fail_free:
336 put_pid(sbi->oz_pgrp);
319 kfree(sbi); 337 kfree(sbi);
320 s->s_fs_info = NULL; 338 s->s_fs_info = NULL;
321fail_unlock: 339fail_unlock: