dev-ioctl.c 17.7 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/*
 * Copyright 2008 Red Hat, Inc. All rights reserved.
 * Copyright 2008 Ian Kent <raven@themaw.net>
 *
 * This file is part of the Linux kernel and is made available under
 * the terms of the GNU General Public License, version 2, or at your
 * option, any later version, incorporated herein by reference.
 */

#include <linux/module.h>
#include <linux/vmalloc.h>
#include <linux/miscdevice.h>
#include <linux/init.h>
#include <linux/wait.h>
#include <linux/namei.h>
#include <linux/fcntl.h>
#include <linux/file.h>
#include <linux/fdtable.h>
#include <linux/sched.h>
#include <linux/compat.h>
#include <linux/syscalls.h>
#include <linux/magic.h>
#include <linux/dcache.h>
#include <linux/uaccess.h>
25
#include <linux/slab.h>
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

#include "autofs_i.h"

/*
 * This module implements an interface for routing autofs ioctl control
 * commands via a miscellaneous device file.
 *
 * The alternate interface is needed because we need to be able open
 * an ioctl file descriptor on an autofs mount that may be covered by
 * another mount. This situation arises when starting automount(8)
 * or other user space daemon which uses direct mounts or offset
 * mounts (used for autofs lazy mount/umount of nested mount trees),
 * which have been left busy at at service shutdown.
 */

#define AUTOFS_DEV_IOCTL_SIZE	sizeof(struct autofs_dev_ioctl)

typedef int (*ioctl_fn)(struct file *, struct autofs_sb_info *,
			struct autofs_dev_ioctl *);

static int check_name(const char *name)
{
	if (!strchr(name, '/'))
		return -EINVAL;
	return 0;
}

/*
 * Check a string doesn't overrun the chunk of
 * memory we copied from user land.
 */
57
static int invalid_str(char *str, size_t size)
58
{
59
60
	if (memchr(str, 0, size))
		return 0;
61
62
63
64
65
66
67
68
69
70
71
72
73
74
	return -EINVAL;
}

/*
 * Check that the user compiled against correct version of autofs
 * misc device code.
 *
 * As well as checking the version compatibility this always copies
 * the kernel interface version out.
 */
static int check_dev_ioctl_version(int cmd, struct autofs_dev_ioctl *param)
{
	int err = 0;

Ian Kent's avatar
Ian Kent committed
75
76
	if ((param->ver_major != AUTOFS_DEV_IOCTL_VERSION_MAJOR) ||
	    (param->ver_minor > AUTOFS_DEV_IOCTL_VERSION_MINOR)) {
77
		pr_warn("ioctl control interface version mismatch: "
78
			"kernel(%u.%u), user(%u.%u), cmd(0x%08x)\n",
79
80
81
			AUTOFS_DEV_IOCTL_VERSION_MAJOR,
			AUTOFS_DEV_IOCTL_VERSION_MINOR,
			param->ver_major, param->ver_minor, cmd);
82
83
84
85
86
87
88
89
90
91
92
93
94
95
		err = -EINVAL;
	}

	/* Fill in the kernel version. */
	param->ver_major = AUTOFS_DEV_IOCTL_VERSION_MAJOR;
	param->ver_minor = AUTOFS_DEV_IOCTL_VERSION_MINOR;

	return err;
}

/*
 * Copy parameter control struct, including a possible path allocated
 * at the end of the struct.
 */
Ian Kent's avatar
Ian Kent committed
96
97
static struct autofs_dev_ioctl *
		copy_dev_ioctl(struct autofs_dev_ioctl __user *in)
98
{
99
	struct autofs_dev_ioctl tmp, *res;
100
101
102
103
104
105
106

	if (copy_from_user(&tmp, in, sizeof(tmp)))
		return ERR_PTR(-EFAULT);

	if (tmp.size < sizeof(tmp))
		return ERR_PTR(-EINVAL);

107
108
109
	if (tmp.size > (PATH_MAX + sizeof(tmp)))
		return ERR_PTR(-ENAMETOOLONG);

110
111
112
113
114
	res = memdup_user(in, tmp.size);
	if (!IS_ERR(res))
		res->size = tmp.size;

	return res;
115
116
117
118
119
120
121
122
123
}

static inline void free_dev_ioctl(struct autofs_dev_ioctl *param)
{
	kfree(param);
}

/*
 * Check sanity of parameter control fields and if a path is present
124
 * check that it is terminated and contains at least one "/".
125
126
127
 */
static int validate_dev_ioctl(int cmd, struct autofs_dev_ioctl *param)
{
128
	int err;
129

130
131
	err = check_dev_ioctl_version(cmd, param);
	if (err) {
132
133
		pr_warn("invalid device control module version "
			"supplied for cmd(0x%08x)\n", cmd);
134
135
136
137
		goto out;
	}

	if (param->size > sizeof(*param)) {
138
		err = invalid_str(param->path, param->size - sizeof(*param));
139
		if (err) {
140
			pr_warn(
141
			  "path string terminator missing for cmd(0x%08x)\n",
142
			  cmd);
143
144
145
			goto out;
		}

146
		err = check_name(param->path);
147
		if (err) {
148
149
			pr_warn("invalid path supplied for cmd(0x%08x)\n",
				cmd);
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
			goto out;
		}
	}

	err = 0;
out:
	return err;
}

/*
 * Get the autofs super block info struct from the file opened on
 * the autofs mount point.
 */
static struct autofs_sb_info *autofs_dev_ioctl_sbi(struct file *f)
{
	struct autofs_sb_info *sbi = NULL;
	struct inode *inode;

	if (f) {
Al Viro's avatar
Al Viro committed
169
		inode = file_inode(f);
170
171
172
173
174
		sbi = autofs4_sbi(inode->i_sb);
	}
	return sbi;
}

175
176
177
178
179
180
181
182
183
184
185
/* Return autofs dev ioctl version */
static int autofs_dev_ioctl_version(struct file *fp,
				    struct autofs_sb_info *sbi,
				    struct autofs_dev_ioctl *param)
{
	/* This should have already been set. */
	param->ver_major = AUTOFS_DEV_IOCTL_VERSION_MAJOR;
	param->ver_minor = AUTOFS_DEV_IOCTL_VERSION_MINOR;
	return 0;
}

186
187
188
189
190
/* Return autofs module protocol version */
static int autofs_dev_ioctl_protover(struct file *fp,
				     struct autofs_sb_info *sbi,
				     struct autofs_dev_ioctl *param)
{
Ian Kent's avatar
Ian Kent committed
191
	param->protover.version = sbi->version;
192
193
194
195
196
197
198
199
	return 0;
}

/* Return autofs module protocol sub version */
static int autofs_dev_ioctl_protosubver(struct file *fp,
					struct autofs_sb_info *sbi,
					struct autofs_dev_ioctl *param)
{
Ian Kent's avatar
Ian Kent committed
200
	param->protosubver.sub_version = sbi->sub_version;
201
202
203
	return 0;
}

204
/* Find the topmost mount satisfying test() */
Al Viro's avatar
Al Viro committed
205
206
207
208
static int find_autofs_mount(const char *pathname,
			     struct path *res,
			     int test(struct path *path, void *data),
			     void *data)
209
{
Al Viro's avatar
Al Viro committed
210
	struct path path;
Ian Kent's avatar
Ian Kent committed
211
212
213
	int err;

	err = kern_path_mountpoint(AT_FDCWD, pathname, &path, 0);
Al Viro's avatar
Al Viro committed
214
215
	if (err)
		return err;
216
	err = -ENOENT;
Al Viro's avatar
Al Viro committed
217
	while (path.dentry == path.mnt->mnt_root) {
218
		if (path.dentry->d_sb->s_magic == AUTOFS_SUPER_MAGIC) {
Al Viro's avatar
Al Viro committed
219
220
221
			if (test(&path, data)) {
				path_get(&path);
				*res = path;
222
				err = 0;
223
				break;
224
225
			}
		}
Al Viro's avatar
Al Viro committed
226
		if (!follow_up(&path))
Al Viro's avatar
Al Viro committed
227
			break;
228
	}
Al Viro's avatar
Al Viro committed
229
	path_put(&path);
230
231
232
	return err;
}

Al Viro's avatar
Al Viro committed
233
static int test_by_dev(struct path *path, void *p)
234
{
235
	return path->dentry->d_sb->s_dev == *(dev_t *)p;
Al Viro's avatar
Al Viro committed
236
}
237

Al Viro's avatar
Al Viro committed
238
239
240
static int test_by_type(struct path *path, void *p)
{
	struct autofs_info *ino = autofs4_dentry_ino(path->dentry);
Ian Kent's avatar
Ian Kent committed
241

Al Viro's avatar
Al Viro committed
242
	return ino && ino->sbi->type & *(unsigned *)p;
243
244
245
246
247
248
}

/*
 * Open a file descriptor on the autofs mount point corresponding
 * to the given path and device number (aka. new_encode_dev(sb->s_dev)).
 */
Al Viro's avatar
Al Viro committed
249
static int autofs_dev_ioctl_open_mountpoint(const char *name, dev_t devid)
250
251
252
{
	int err, fd;

253
	fd = get_unused_fd_flags(O_CLOEXEC);
254
	if (likely(fd >= 0)) {
Al Viro's avatar
Al Viro committed
255
256
257
258
		struct file *filp;
		struct path path;

		err = find_autofs_mount(name, &path, test_by_dev, &devid);
259
260
261
262
		if (err)
			goto out;

		/*
Al Viro's avatar
Al Viro committed
263
		 * Find autofs super block that has the device number
264
265
266
		 * corresponding to the autofs fs we want to open.
		 */

267
268
		filp = dentry_open(&path, O_RDONLY, current_cred());
		path_put(&path);
269
270
271
272
273
		if (IS_ERR(filp)) {
			err = PTR_ERR(filp);
			goto out;
		}

274
		fd_install(fd, filp);
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
	}

	return fd;

out:
	put_unused_fd(fd);
	return err;
}

/* Open a file descriptor on an autofs mount point */
static int autofs_dev_ioctl_openmount(struct file *fp,
				      struct autofs_sb_info *sbi,
				      struct autofs_dev_ioctl *param)
{
	const char *path;
	dev_t devid;
	int err, fd;

	/* param->path has already been checked */
Ian Kent's avatar
Ian Kent committed
294
	if (!param->openmount.devid)
295
296
297
298
299
		return -EINVAL;

	param->ioctlfd = -1;

	path = param->path;
Al Viro's avatar
Al Viro committed
300
	devid = new_decode_dev(param->openmount.devid);
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331

	err = 0;
	fd = autofs_dev_ioctl_open_mountpoint(path, devid);
	if (unlikely(fd < 0)) {
		err = fd;
		goto out;
	}

	param->ioctlfd = fd;
out:
	return err;
}

/* Close file descriptor allocated above (user can also use close(2)). */
static int autofs_dev_ioctl_closemount(struct file *fp,
				       struct autofs_sb_info *sbi,
				       struct autofs_dev_ioctl *param)
{
	return sys_close(param->ioctlfd);
}

/*
 * Send "ready" status for an existing wait (either a mount or an expire
 * request).
 */
static int autofs_dev_ioctl_ready(struct file *fp,
				  struct autofs_sb_info *sbi,
				  struct autofs_dev_ioctl *param)
{
	autofs_wqt_t token;

Ian Kent's avatar
Ian Kent committed
332
	token = (autofs_wqt_t) param->ready.token;
333
334
335
336
337
338
339
340
341
342
343
344
345
346
	return autofs4_wait_release(sbi, token, 0);
}

/*
 * Send "fail" status for an existing wait (either a mount or an expire
 * request).
 */
static int autofs_dev_ioctl_fail(struct file *fp,
				 struct autofs_sb_info *sbi,
				 struct autofs_dev_ioctl *param)
{
	autofs_wqt_t token;
	int status;

Ian Kent's avatar
Ian Kent committed
347
	token = (autofs_wqt_t) param->fail.token;
348
	status = param->fail.status < 0 ? param->fail.status : -ENOENT;
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
	return autofs4_wait_release(sbi, token, status);
}

/*
 * Set the pipe fd for kernel communication to the daemon.
 *
 * Normally this is set at mount using an option but if we
 * are reconnecting to a busy mount then we need to use this
 * to tell the autofs mount about the new kernel pipe fd. In
 * order to protect mounts against incorrectly setting the
 * pipefd we also require that the autofs mount be catatonic.
 *
 * This also sets the process group id used to identify the
 * controlling process (eg. the owning automount(8) daemon).
 */
static int autofs_dev_ioctl_setpipefd(struct file *fp,
				      struct autofs_sb_info *sbi,
				      struct autofs_dev_ioctl *param)
{
	int pipefd;
	int err = 0;
370
	struct pid *new_pid = NULL;
371

Ian Kent's avatar
Ian Kent committed
372
	if (param->setpipefd.pipefd == -1)
373
374
		return -EINVAL;

Ian Kent's avatar
Ian Kent committed
375
	pipefd = param->setpipefd.pipefd;
376
377
378
379
380
381

	mutex_lock(&sbi->wq_mutex);
	if (!sbi->catatonic) {
		mutex_unlock(&sbi->wq_mutex);
		return -EBUSY;
	} else {
382
383
384
385
386
		struct file *pipe;

		new_pid = get_task_pid(current, PIDTYPE_PGID);

		if (ns_of_pid(new_pid) != ns_of_pid(sbi->oz_pgrp)) {
387
			pr_warn("not allowed to change PID namespace\n");
388
389
390
391
392
			err = -EINVAL;
			goto out;
		}

		pipe = fget(pipefd);
393
394
395
396
		if (!pipe) {
			err = -EBADF;
			goto out;
		}
397
		if (autofs_prepare_pipe(pipe) < 0) {
398
399
400
401
			err = -EPIPE;
			fput(pipe);
			goto out;
		}
402
		swap(sbi->oz_pgrp, new_pid);
403
404
405
406
407
		sbi->pipefd = pipefd;
		sbi->pipe = pipe;
		sbi->catatonic = 0;
	}
out:
408
	put_pid(new_pid);
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
	mutex_unlock(&sbi->wq_mutex);
	return err;
}

/*
 * Make the autofs mount point catatonic, no longer responsive to
 * mount requests. Also closes the kernel pipe file descriptor.
 */
static int autofs_dev_ioctl_catatonic(struct file *fp,
				      struct autofs_sb_info *sbi,
				      struct autofs_dev_ioctl *param)
{
	autofs4_catatonic_mode(sbi);
	return 0;
}

/* Set the autofs mount timeout */
static int autofs_dev_ioctl_timeout(struct file *fp,
				    struct autofs_sb_info *sbi,
				    struct autofs_dev_ioctl *param)
{
	unsigned long timeout;

Ian Kent's avatar
Ian Kent committed
432
433
	timeout = param->timeout.timeout;
	param->timeout.timeout = sbi->exp_timeout / HZ;
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
	sbi->exp_timeout = timeout * HZ;
	return 0;
}

/*
 * Return the uid and gid of the last request for the mount
 *
 * When reconstructing an autofs mount tree with active mounts
 * we need to re-connect to mounts that may have used the original
 * process uid and gid (or string variations of them) for mount
 * lookups within the map entry.
 */
static int autofs_dev_ioctl_requester(struct file *fp,
				      struct autofs_sb_info *sbi,
				      struct autofs_dev_ioctl *param)
{
	struct autofs_info *ino;
Al Viro's avatar
Al Viro committed
451
	struct path path;
452
453
454
455
456
457
458
459
	dev_t devid;
	int err = -ENOENT;

	if (param->size <= sizeof(*param)) {
		err = -EINVAL;
		goto out;
	}

Al Viro's avatar
Al Viro committed
460
	devid = sbi->sb->s_dev;
461

Ian Kent's avatar
Ian Kent committed
462
	param->requester.uid = param->requester.gid = -1;
463

Al Viro's avatar
Al Viro committed
464
	err = find_autofs_mount(param->path, &path, test_by_dev, &devid);
465
466
467
	if (err)
		goto out;

Al Viro's avatar
Al Viro committed
468
	ino = autofs4_dentry_ino(path.dentry);
469
470
	if (ino) {
		err = 0;
471
		autofs4_expire_wait(path.dentry, 0);
472
		spin_lock(&sbi->fs_lock);
Ian Kent's avatar
Ian Kent committed
473
474
475
476
		param->requester.uid =
			from_kuid_munged(current_user_ns(), ino->uid);
		param->requester.gid =
			from_kgid_munged(current_user_ns(), ino->gid);
477
478
		spin_unlock(&sbi->fs_lock);
	}
Al Viro's avatar
Al Viro committed
479
	path_put(&path);
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
out:
	return err;
}

/*
 * Call repeatedly until it returns -EAGAIN, meaning there's nothing
 * more that can be done.
 */
static int autofs_dev_ioctl_expire(struct file *fp,
				   struct autofs_sb_info *sbi,
				   struct autofs_dev_ioctl *param)
{
	struct vfsmount *mnt;
	int how;

Ian Kent's avatar
Ian Kent committed
495
	how = param->expire.how;
496
497
	mnt = fp->f_path.mnt;

498
	return autofs4_do_expire_multi(sbi->sb, mnt, sbi, how);
499
500
501
502
503
504
505
}

/* Check if autofs mount point is in use */
static int autofs_dev_ioctl_askumount(struct file *fp,
				      struct autofs_sb_info *sbi,
				      struct autofs_dev_ioctl *param)
{
Ian Kent's avatar
Ian Kent committed
506
	param->askumount.may_umount = 0;
507
	if (may_umount(fp->f_path.mnt))
Ian Kent's avatar
Ian Kent committed
508
		param->askumount.may_umount = 1;
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
	return 0;
}

/*
 * Check if the given path is a mountpoint.
 *
 * If we are supplied with the file descriptor of an autofs
 * mount we're looking for a specific mount. In this case
 * the path is considered a mountpoint if it is itself a
 * mountpoint or contains a mount, such as a multi-mount
 * without a root mount. In this case we return 1 if the
 * path is a mount point and the super magic of the covering
 * mount if there is one or 0 if it isn't a mountpoint.
 *
 * If we aren't supplied with a file descriptor then we
524
525
526
527
528
 * lookup the path and check if it is the root of a mount.
 * If a type is given we are looking for a particular autofs
 * mount and if we don't find a match we return fail. If the
 * located path is the root of a mount we return 1 along with
 * the super magic of the mount or 0 otherwise.
529
530
531
532
533
534
535
536
 *
 * In both cases the the device number (as returned by
 * new_encode_dev()) is also returned.
 */
static int autofs_dev_ioctl_ismountpoint(struct file *fp,
					 struct autofs_sb_info *sbi,
					 struct autofs_dev_ioctl *param)
{
Al Viro's avatar
Al Viro committed
537
538
	struct path path;
	const char *name;
539
	unsigned int type;
Ian Kent's avatar
Ian Kent committed
540
	unsigned int devid, magic;
541
542
543
544
545
546
547
	int err = -ENOENT;

	if (param->size <= sizeof(*param)) {
		err = -EINVAL;
		goto out;
	}

Al Viro's avatar
Al Viro committed
548
	name = param->path;
Ian Kent's avatar
Ian Kent committed
549
	type = param->ismountpoint.in.type;
550

Ian Kent's avatar
Ian Kent committed
551
552
	param->ismountpoint.out.devid = devid = 0;
	param->ismountpoint.out.magic = magic = 0;
553
554

	if (!fp || param->ioctlfd == -1) {
Al Viro's avatar
Al Viro committed
555
		if (autofs_type_any(type))
556
557
			err = kern_path_mountpoint(AT_FDCWD,
						   name, &path, LOOKUP_FOLLOW);
Al Viro's avatar
Al Viro committed
558
		else
559
560
			err = find_autofs_mount(name, &path,
						test_by_type, &type);
Al Viro's avatar
Al Viro committed
561
562
		if (err)
			goto out;
563
		devid = new_encode_dev(path.dentry->d_sb->s_dev);
564
		err = 0;
565
		if (path.mnt->mnt_root == path.dentry) {
566
			err = 1;
567
			magic = path.dentry->d_sb->s_magic;
568
569
		}
	} else {
Al Viro's avatar
Al Viro committed
570
		dev_t dev = sbi->sb->s_dev;
571

Al Viro's avatar
Al Viro committed
572
		err = find_autofs_mount(name, &path, test_by_dev, &dev);
573
574
575
		if (err)
			goto out;

Al Viro's avatar
Al Viro committed
576
		devid = new_encode_dev(dev);
577

Al Viro's avatar
Al Viro committed
578
		err = have_submounts(path.dentry);
579

580
		if (follow_down_one(&path))
581
			magic = path.dentry->d_sb->s_magic;
582
583
	}

Ian Kent's avatar
Ian Kent committed
584
585
	param->ismountpoint.out.devid = devid;
	param->ismountpoint.out.magic = magic;
Al Viro's avatar
Al Viro committed
586
	path_put(&path);
587
588
589
590
591
592
593
594
595
596
597
598
599
out:
	return err;
}

/*
 * Our range of ioctl numbers isn't 0 based so we need to shift
 * the array index by _IOC_NR(AUTOFS_CTL_IOC_FIRST) for the table
 * lookup.
 */
#define cmd_idx(cmd)	(cmd - _IOC_NR(AUTOFS_DEV_IOCTL_IOC_FIRST))

static ioctl_fn lookup_dev_ioctl(unsigned int cmd)
{
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
	static ioctl_fn _ioctls[] = {
		autofs_dev_ioctl_version,
		autofs_dev_ioctl_protover,
		autofs_dev_ioctl_protosubver,
		autofs_dev_ioctl_openmount,
		autofs_dev_ioctl_closemount,
		autofs_dev_ioctl_ready,
		autofs_dev_ioctl_fail,
		autofs_dev_ioctl_setpipefd,
		autofs_dev_ioctl_catatonic,
		autofs_dev_ioctl_timeout,
		autofs_dev_ioctl_requester,
		autofs_dev_ioctl_expire,
		autofs_dev_ioctl_askumount,
		autofs_dev_ioctl_ismountpoint,
615
616
617
	};
	unsigned int idx = cmd_idx(cmd);

618
	return (idx >= ARRAY_SIZE(_ioctls)) ? NULL : _ioctls[idx];
619
620
621
}

/* ioctl dispatcher */
Ian Kent's avatar
Ian Kent committed
622
623
static int _autofs_dev_ioctl(unsigned int command,
			     struct autofs_dev_ioctl __user *user)
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
{
	struct autofs_dev_ioctl *param;
	struct file *fp;
	struct autofs_sb_info *sbi;
	unsigned int cmd_first, cmd;
	ioctl_fn fn = NULL;
	int err = 0;

	/* only root can play with this */
	if (!capable(CAP_SYS_ADMIN))
		return -EPERM;

	cmd_first = _IOC_NR(AUTOFS_DEV_IOCTL_IOC_FIRST);
	cmd = _IOC_NR(command);

	if (_IOC_TYPE(command) != _IOC_TYPE(AUTOFS_DEV_IOCTL_IOC_FIRST) ||
640
	    cmd - cmd_first > AUTOFS_DEV_IOCTL_IOC_COUNT) {
641
642
643
644
645
646
647
648
649
650
651
652
653
654
		return -ENOTTY;
	}

	/* Copy the parameters into kernel space. */
	param = copy_dev_ioctl(user);
	if (IS_ERR(param))
		return PTR_ERR(param);

	err = validate_dev_ioctl(command, param);
	if (err)
		goto out;

	fn = lookup_dev_ioctl(cmd);
	if (!fn) {
655
		pr_warn("unknown command 0x%08x\n", command);
656
657
		err = -ENOTTY;
		goto out;
658
659
660
661
662
663
664
665
	}

	fp = NULL;
	sbi = NULL;

	/*
	 * For obvious reasons the openmount can't have a file
	 * descriptor yet. We don't take a reference to the
666
667
	 * file during close to allow for immediate release,
	 * and the same for retrieving ioctl version.
668
	 */
669
670
	if (cmd != AUTOFS_DEV_IOCTL_VERSION_CMD &&
	    cmd != AUTOFS_DEV_IOCTL_OPENMOUNT_CMD &&
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
	    cmd != AUTOFS_DEV_IOCTL_CLOSEMOUNT_CMD) {
		fp = fget(param->ioctlfd);
		if (!fp) {
			if (cmd == AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD)
				goto cont;
			err = -EBADF;
			goto out;
		}

		sbi = autofs_dev_ioctl_sbi(fp);
		if (!sbi || sbi->magic != AUTOFS_SBI_MAGIC) {
			err = -EINVAL;
			fput(fp);
			goto out;
		}

		/*
		 * Admin needs to be able to set the mount catatonic in
		 * order to be able to perform the re-open.
		 */
		if (!autofs4_oz_mode(sbi) &&
		    cmd != AUTOFS_DEV_IOCTL_CATATONIC_CMD) {
			err = -EACCES;
			fput(fp);
			goto out;
		}
	}
cont:
	err = fn(fp, sbi, param);

	if (fp)
		fput(fp);
	if (err >= 0 && copy_to_user(user, param, AUTOFS_DEV_IOCTL_SIZE))
		err = -EFAULT;
out:
	free_dev_ioctl(param);
	return err;
}

static long autofs_dev_ioctl(struct file *file, uint command, ulong u)
{
	int err;
Ian Kent's avatar
Ian Kent committed
713

714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
	err = _autofs_dev_ioctl(command, (struct autofs_dev_ioctl __user *) u);
	return (long) err;
}

#ifdef CONFIG_COMPAT
static long autofs_dev_ioctl_compat(struct file *file, uint command, ulong u)
{
	return (long) autofs_dev_ioctl(file, command, (ulong) compat_ptr(u));
}
#else
#define autofs_dev_ioctl_compat NULL
#endif

static const struct file_operations _dev_ioctl_fops = {
	.unlocked_ioctl	 = autofs_dev_ioctl,
	.compat_ioctl = autofs_dev_ioctl_compat,
	.owner	 = THIS_MODULE,
731
	.llseek = noop_llseek,
732
733
734
};

static struct miscdevice _autofs_dev_ioctl_misc = {
735
	.minor		= AUTOFS_MINOR,
Ian Kent's avatar
Ian Kent committed
736
737
	.name		= AUTOFS_DEVICE_NAME,
	.fops		= &_dev_ioctl_fops
738
739
};

740
741
742
MODULE_ALIAS_MISCDEV(AUTOFS_MINOR);
MODULE_ALIAS("devname:autofs");

743
/* Register/deregister misc character device */
744
int __init autofs_dev_ioctl_init(void)
745
746
747
748
749
{
	int r;

	r = misc_register(&_autofs_dev_ioctl_misc);
	if (r) {
750
		pr_err("misc_register failed for control device\n");
751
752
753
754
755
756
757
758
759
760
		return r;
	}

	return 0;
}

void autofs_dev_ioctl_exit(void)
{
	misc_deregister(&_autofs_dev_ioctl_misc);
}