1
/* ----------------------------------------------------------------------- *
3
* ctl-dev-lib.c - module for Linux automount mount table lookup functions
5
* Copyright 2008 Red Hat, Inc. All rights reserved.
6
* Copyright 2008 Ian Kent <raven@themaw.net> - All Rights Reserved
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
11
* USA; either version 2 of the License, or (at your option) any later
12
* version; incorporated herein by reference.
14
* ----------------------------------------------------------------------- */
21
#include <sys/types.h>
23
#include <sys/ioctl.h>
28
#include "automount.h"
30
/* ioctld control function interface */
31
static struct ioctl_ctl ctl = { -1, NULL };
33
#ifndef AUTOFS_SUPER_MAGIC
34
#define AUTOFS_SUPER_MAGIC 0x0187
38
* Define functions for autofs ioctl control.
40
* We provide two interfaces. One which routes ioctls via a
41
* miscelaneous device node and can be used to obtain an ioctl
42
* file descriptor for autofs mounts that are covered by an
43
* active mount (eg. active direct or multi-mount offsets).
44
* The other provides the traditional autofs ioctl implementation.
46
* The miscielaneous device control functions are prefixed with
47
* dev_ctl_ and the traditional ones are prefixed with ioctl_.
49
static int dev_ioctl_version(unsigned int, int, struct autofs_dev_ioctl *);
50
static int dev_ioctl_protover(unsigned int, int, unsigned int *);
51
static int dev_ioctl_protosubver(unsigned int, int, unsigned int *);
52
static int dev_ioctl_mount_device(unsigned int, const char *, unsigned int, dev_t *);
53
static int dev_ioctl_open(unsigned int, int *, dev_t, const char *);
54
static int dev_ioctl_close(unsigned int, int);
55
static int dev_ioctl_send_ready(unsigned int, int, unsigned int);
56
static int dev_ioctl_send_fail(unsigned int, int, unsigned int, int);
57
static int dev_ioctl_setpipefd(unsigned int, int, int);
58
static int dev_ioctl_catatonic(unsigned int, int);
59
static int dev_ioctl_timeout(unsigned int, int, time_t *);
60
static int dev_ioctl_requestor(unsigned int, int, const char *, uid_t *, gid_t *);
61
static int dev_ioctl_expire(unsigned int, int, const char *, unsigned int);
62
static int dev_ioctl_askumount(unsigned int, int, unsigned int *);
63
static int dev_ioctl_ismountpoint(unsigned int, int, const char *, unsigned int *);
65
static int ioctl_protover(unsigned int, int, unsigned int *);
66
static int ioctl_protosubver(unsigned int, int, unsigned int *);
67
static int ioctl_mount_device(unsigned int, const char *, unsigned int, dev_t *);
68
static int ioctl_open(unsigned int, int *, dev_t, const char *);
69
static int ioctl_close(unsigned int, int);
70
static int ioctl_send_ready(unsigned int, int, unsigned int);
71
static int ioctl_send_fail(unsigned int, int, unsigned int, int);
72
static int ioctl_catatonic(unsigned int, int);
73
static int ioctl_timeout(unsigned int, int, time_t *);
74
static int ioctl_expire(unsigned int, int, const char *, unsigned int);
75
static int ioctl_askumount(unsigned int, int, unsigned int *);
77
static struct ioctl_ops dev_ioctl_ops = {
78
.version = dev_ioctl_version,
79
.protover = dev_ioctl_protover,
80
.protosubver = dev_ioctl_protosubver,
81
.mount_device = dev_ioctl_mount_device,
82
.open = dev_ioctl_open,
83
.close = dev_ioctl_close,
84
.send_ready = dev_ioctl_send_ready,
85
.send_fail = dev_ioctl_send_fail,
86
.setpipefd = dev_ioctl_setpipefd,
87
.catatonic = dev_ioctl_catatonic,
88
.timeout = dev_ioctl_timeout,
89
.requestor = dev_ioctl_requestor,
90
.expire = dev_ioctl_expire,
91
.askumount = dev_ioctl_askumount,
92
.ismountpoint = dev_ioctl_ismountpoint
95
static struct ioctl_ops ioctl_ops = {
97
.protover = ioctl_protover,
98
.protosubver = ioctl_protosubver,
99
.mount_device = ioctl_mount_device,
101
.close = ioctl_close,
102
.send_ready = ioctl_send_ready,
103
.send_fail = ioctl_send_fail,
105
.catatonic = ioctl_catatonic,
106
.timeout = ioctl_timeout,
108
.expire = ioctl_expire,
109
.askumount = ioctl_askumount,
114
* Allocate the control struct that holds the misc device file
115
* descriptor and operation despatcher table.
117
void init_ioctl_ctl(void)
124
devfd = open(CONTROL_DEVICE, O_RDONLY);
126
ctl.ops = &ioctl_ops;
128
struct autofs_dev_ioctl param;
130
int cl_flags = fcntl(devfd, F_GETFD, 0);
131
if (cl_flags != -1) {
132
cl_flags |= FD_CLOEXEC;
133
fcntl(devfd, F_SETFD, cl_flags);
136
* Check compile version against kernel.
137
* Selinux may allow us to open the device but not
138
* actually allow us to do anything.
140
init_autofs_dev_ioctl(¶m);
141
if (ioctl(devfd, AUTOFS_DEV_IOCTL_VERSION, ¶m) == -1) {
143
ctl.ops = &ioctl_ops;
146
ctl.ops = &dev_ioctl_ops;
152
void close_ioctl_ctl(void)
154
if (ctl.devfd != -1) {
162
/* Return a pointer to the operations control struct */
163
struct ioctl_ops *get_ioctl_ops(void)
170
/* Get kenrel version of misc device code */
171
static int dev_ioctl_version(unsigned int logopt,
172
int ioctlfd, struct autofs_dev_ioctl *param)
174
param->ioctlfd = ioctlfd;
176
if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_VERSION, param) == -1)
182
/* Get major version of autofs kernel module mount protocol */
183
static int dev_ioctl_protover(unsigned int logopt,
184
int ioctlfd, unsigned int *major)
186
struct autofs_dev_ioctl param;
188
init_autofs_dev_ioctl(¶m);
189
param.ioctlfd = ioctlfd;
191
if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_PROTOVER, ¶m) == -1)
194
*major = param.protover.version;
199
static int ioctl_protover(unsigned int logopt,
200
int ioctlfd, unsigned int *major)
202
return ioctl(ioctlfd, AUTOFS_IOC_PROTOVER, major);
205
/* Get minor version of autofs kernel module mount protocol */
206
static int dev_ioctl_protosubver(unsigned int logopt,
207
int ioctlfd, unsigned int *minor)
209
struct autofs_dev_ioctl param;
211
init_autofs_dev_ioctl(¶m);
212
param.ioctlfd = ioctlfd;
214
if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_PROTOSUBVER, ¶m) == -1)
217
*minor = param.protosubver.sub_version;
222
static int ioctl_protosubver(unsigned int logopt,
223
int ioctlfd, unsigned int *minor)
225
return ioctl(ioctlfd, AUTOFS_IOC_PROTOSUBVER, minor);
229
* Allocate a parameter struct for misc device ioctl used when
230
* opening an autofs mount point. Attach the path to the end
231
* of the struct. and lookup the device number if not given.
232
* Locating the device number relies on the mount option
233
* "dev=<device number>" being present in the autofs fs mount
236
static struct autofs_dev_ioctl *alloc_dev_ioctl_open(const char *path, dev_t devid)
238
struct autofs_dev_ioctl *ioctl;
245
p_len = strlen(path);
246
size = sizeof(struct autofs_dev_ioctl) + p_len + 1;
247
ioctl = malloc(size);
253
init_autofs_dev_ioctl(ioctl);
255
memcpy(ioctl->path, path, p_len);
256
ioctl->path[p_len] = '\0';
257
ioctl->openmount.devid = devno;
262
static void free_dev_ioctl_open(struct autofs_dev_ioctl *ioctl)
269
* Allocate a parameter struct for misc device ioctl which includes
270
* a path. This is used when getting the last mount requestor uid
271
* and gid and when checking if a path within the autofs filesystem
272
* is a mount point. We add the path to the end of the struct.
274
static struct autofs_dev_ioctl *alloc_dev_ioctl_path(int ioctlfd, const char *path)
276
struct autofs_dev_ioctl *ioctl;
282
p_len = strlen(path);
283
size = sizeof(struct autofs_dev_ioctl) + p_len + 1;
284
ioctl = malloc(size);
290
init_autofs_dev_ioctl(ioctl);
291
ioctl->ioctlfd = ioctlfd;
293
memcpy(ioctl->path, path, p_len);
294
ioctl->path[p_len] = '\0';
299
static void free_dev_ioctl_path(struct autofs_dev_ioctl *ioctl)
306
* Find the device number of an autofs mount with given path and
307
* type (eg..AUTOFS_TYPE_DIRECT). The device number is used by
308
* the kernel to identify the autofs super block when searching
311
static int dev_ioctl_mount_device(unsigned int logopt, const char *path, unsigned int type, dev_t *devid)
313
struct autofs_dev_ioctl *param;
323
param = alloc_dev_ioctl_path(-1, path);
326
param->ismountpoint.in.type = type;
328
err = ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_ISMOUNTPOINT, param);
330
int save_errno = errno;
331
free_dev_ioctl_path(param);
337
*devid = param->ismountpoint.out.devid;
339
free_dev_ioctl_path(param);
344
static int ioctl_mount_device(unsigned int logopt,
345
const char *path, unsigned int type,
351
/* Get a file descriptor for control operations */
352
static int dev_ioctl_open(unsigned int logopt,
353
int *ioctlfd, dev_t devid, const char *path)
355
struct autofs_dev_ioctl *param;
359
param = alloc_dev_ioctl_open(path, devid);
363
if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_OPENMOUNT, param) == -1) {
364
int save_errno = errno;
365
free_dev_ioctl_open(param);
370
*ioctlfd = param->ioctlfd;
372
free_dev_ioctl_open(param);
377
static int ioctl_open(unsigned int logopt,
378
int *ioctlfd, dev_t devid, const char *path)
381
int save_errno, fd, cl_flags;
385
fd = open(path, O_RDONLY);
389
cl_flags = fcntl(fd, F_GETFD, 0);
390
if (cl_flags != -1) {
391
cl_flags |= FD_CLOEXEC;
392
fcntl(fd, F_SETFD, cl_flags);
395
if (fstatfs(fd, &sfs) == -1) {
400
if (sfs.f_type != AUTOFS_SUPER_MAGIC) {
415
static int dev_ioctl_close(unsigned int logopt, int ioctlfd)
417
struct autofs_dev_ioctl param;
419
init_autofs_dev_ioctl(¶m);
420
param.ioctlfd = ioctlfd;
422
if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_CLOSEMOUNT, ¶m) == -1)
428
static int ioctl_close(unsigned int logopt, int ioctlfd)
430
return close(ioctlfd);
433
/* Send ready status for given token */
434
static int dev_ioctl_send_ready(unsigned int logopt,
435
int ioctlfd, unsigned int token)
437
struct autofs_dev_ioctl param;
444
debug(logopt, "token = %d", token);
446
init_autofs_dev_ioctl(¶m);
447
param.ioctlfd = ioctlfd;
448
param.ready.token = token;
450
if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_READY, ¶m) == -1) {
451
char *estr, buf[MAX_ERR_BUF];
452
int save_errno = errno;
453
estr = strerror_r(errno, buf, MAX_ERR_BUF);
454
logerr("AUTOFS_DEV_IOCTL_READY: error %s", estr);
461
static int ioctl_send_ready(unsigned int logopt,
462
int ioctlfd, unsigned int token)
469
debug(logopt, "token = %d", token);
471
if (ioctl(ioctlfd, AUTOFS_IOC_READY, token) == -1) {
472
char *estr, buf[MAX_ERR_BUF];
473
int save_errno = errno;
474
estr = strerror_r(errno, buf, MAX_ERR_BUF);
475
logerr("AUTOFS_IOC_READY: error %s", estr);
483
* Send ready status for given token.
485
* The device node ioctl implementation allows for sending a status
486
* of other than ENOENT, unlike the tradional interface.
488
static int dev_ioctl_send_fail(unsigned int logopt,
489
int ioctlfd, unsigned int token, int status)
491
struct autofs_dev_ioctl param;
498
debug(logopt, "token = %d", token);
500
init_autofs_dev_ioctl(¶m);
501
param.ioctlfd = ioctlfd;
502
param.fail.token = token;
503
param.fail.status = status;
505
if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_FAIL, ¶m) == -1) {
506
char *estr, buf[MAX_ERR_BUF];
507
int save_errno = errno;
508
estr = strerror_r(errno, buf, MAX_ERR_BUF);
509
logerr("AUTOFS_DEV_IOCTL_FAIL: error %s", estr);
516
static int ioctl_send_fail(unsigned int logopt,
517
int ioctlfd, unsigned int token, int status)
524
debug(logopt, "token = %d", token);
526
if (ioctl(ioctlfd, AUTOFS_IOC_FAIL, token) == -1) {
527
char *estr, buf[MAX_ERR_BUF];
528
int save_errno = errno;
529
estr = strerror_r(errno, buf, MAX_ERR_BUF);
530
logerr("AUTOFS_IOC_FAIL: error %s", estr);
538
* Set the pipe fd for kernel communication.
540
* Normally this is set at mount using an option but if we
541
* are reconnecting to a busy mount then we need to use this
542
* to tell the autofs kernel module about the new pipe fd. In
543
* order to protect mounts against incorrectly setting the
544
* pipefd we also require that the autofs mount be catatonic.
546
* If successful this also sets the process group id used to
547
* identify the controlling process to the process group of
550
static int dev_ioctl_setpipefd(unsigned int logopt, int ioctlfd, int pipefd)
552
struct autofs_dev_ioctl param;
559
init_autofs_dev_ioctl(¶m);
560
param.ioctlfd = ioctlfd;
561
param.setpipefd.pipefd = pipefd;
563
if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_SETPIPEFD, ¶m) == -1)
570
* Make the autofs mount point catatonic, no longer responsive to
571
* mount requests. Also closes the kernel pipe file descriptor.
573
static int dev_ioctl_catatonic(unsigned int logopt, int ioctlfd)
575
struct autofs_dev_ioctl param;
577
init_autofs_dev_ioctl(¶m);
578
param.ioctlfd = ioctlfd;
580
if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_CATATONIC, ¶m) == -1)
586
static int ioctl_catatonic(unsigned int logopt, int ioctlfd)
588
return ioctl(ioctlfd, AUTOFS_IOC_CATATONIC, 0);
591
/* Set the autofs mount timeout */
592
static int dev_ioctl_timeout(unsigned int logopt, int ioctlfd, time_t *timeout)
594
struct autofs_dev_ioctl param;
596
init_autofs_dev_ioctl(¶m);
597
param.ioctlfd = ioctlfd;
598
param.timeout.timeout = *timeout;
600
if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_TIMEOUT, ¶m) == -1)
603
*timeout = param.timeout.timeout;
608
static int ioctl_timeout(unsigned int logopt, int ioctlfd, time_t *timeout)
610
return ioctl(ioctlfd, AUTOFS_IOC_SETTIMEOUT, timeout);
614
* Get the uid and gid of the last request for the mountpoint, path.
616
* When reconstructing an autofs mount tree with active mounts
617
* we need to re-connect to mounts that may have used the original
618
* process uid and gid (or string variations of them) for mount
619
* lookups within the map entry.
621
static int dev_ioctl_requestor(unsigned int logopt,
622
int ioctlfd, const char *path,
623
uid_t *uid, gid_t *gid)
625
struct autofs_dev_ioctl *param;
635
param = alloc_dev_ioctl_path(ioctlfd, path);
639
err = ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_REQUESTER, param);
641
int save_errno = errno;
642
free_dev_ioctl_open(param);
647
*uid = param->requester.uid;
648
*gid = param->requester.gid;
650
free_dev_ioctl_path(param);
656
* Call repeatedly until it returns EAGAIN, meaning there's nothing
657
* more that can be done.
659
static int expire(unsigned int logopt,
660
int cmd, int fd, int ioctlfd, const char *path, void *arg)
662
int ret, retries = EXPIRE_RETRIES;
663
unsigned int may_umount;
666
struct timespec tm = {0, 100000000};
668
/* Ggenerate expire message for the mount. */
669
ret = ioctl(fd, cmd, arg);
671
/* Mount has gone away */
672
if (errno == EBADF || errno == EINVAL)
676
* Other than EAGAIN is an expire error so continue.
677
* Kernel will try the next mount for indirect maps
678
* and the same mount again for direct maps, limited
684
nanosleep(&tm, NULL);
688
if (ctl.ops->askumount(logopt, ioctlfd, &may_umount))
697
static int dev_ioctl_expire(unsigned int logopt,
698
int ioctlfd, const char *path, unsigned int when)
700
struct autofs_dev_ioctl param;
702
init_autofs_dev_ioctl(¶m);
703
param.ioctlfd = ioctlfd;
704
param.expire.how = when;
706
return expire(logopt, AUTOFS_DEV_IOCTL_EXPIRE,
707
ctl.devfd, ioctlfd, path, (void *) ¶m);
710
static int ioctl_expire(unsigned int logopt,
711
int ioctlfd, const char *path, unsigned int when)
713
return expire(logopt, AUTOFS_IOC_EXPIRE_MULTI,
714
ioctlfd, ioctlfd, path, (void *) &when);
717
/* Check if autofs mount point is in use */
718
static int dev_ioctl_askumount(unsigned int logopt,
719
int ioctlfd, unsigned int *busy)
721
struct autofs_dev_ioctl param;
723
init_autofs_dev_ioctl(¶m);
724
param.ioctlfd = ioctlfd;
726
if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_ASKUMOUNT, ¶m) == -1)
729
*busy = param.askumount.may_umount;
734
static int ioctl_askumount(unsigned int logopt,
735
int ioctlfd, unsigned int *busy)
737
return ioctl(ioctlfd, AUTOFS_IOC_ASKUMOUNT, busy);
741
* Check if the given path is a mountpoint.
743
* The path is considered a mountpoint if it is itself a mountpoint
744
* or contains a mount, such as a multi-mount without a root mount.
745
* In addition, if the path is itself a mountpoint we return whether
746
* the mounted file system is an autofs filesystem or other file
749
static int dev_ioctl_ismountpoint(unsigned int logopt,
750
int ioctlfd, const char *path,
751
unsigned int *mountpoint)
753
struct autofs_dev_ioctl *param;
763
param = alloc_dev_ioctl_path(ioctlfd, path);
766
set_autofs_type_any(¶m->ismountpoint.in.type);
768
err = ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_ISMOUNTPOINT, param);
770
int save_errno = errno;
771
free_dev_ioctl_path(param);
777
*mountpoint = DEV_IOCTL_IS_MOUNTED;
779
if (param->ismountpoint.out.magic) {
780
if (param->ismountpoint.out.magic == AUTOFS_SUPER_MAGIC)
781
*mountpoint |= DEV_IOCTL_IS_AUTOFS;
783
*mountpoint |= DEV_IOCTL_IS_OTHER;
787
free_dev_ioctl_path(param);