1/* 2 * smbumount.c 3 * 4 * Copyright (C) 1995-1998 by Volker Lendecke 5 * 6 */ 7 8#include "includes.h" 9 10#include <mntent.h> 11 12#include <asm/types.h> 13#include <asm/posix_types.h> 14#include <linux/smb.h> 15#include <linux/smb_mount.h> 16#include <linux/smb_fs.h> 17 18/* This is a (hopefully) temporary hack due to the fact that 19 sizeof( uid_t ) != sizeof( __kernel_uid_t ) under glibc. 20 This may change in the future and smb.h may get fixed in the 21 future. In the mean time, it's ugly hack time - get over it. 22*/ 23#undef SMB_IOC_GETMOUNTUID 24#define SMB_IOC_GETMOUNTUID _IOR('u', 1, __kernel_uid_t) 25 26#ifndef O_NOFOLLOW 27#define O_NOFOLLOW 0400000 28#endif 29 30static void 31usage(void) 32{ 33 printf("usage: smbumount mountpoint\n"); 34} 35 36static int 37umount_ok(const char *mount_point) 38{ 39 /* we set O_NOFOLLOW to prevent users playing games with symlinks to 40 umount filesystems they don't own */ 41 int fid = open(mount_point, O_RDONLY|O_NOFOLLOW, 0); 42 __kernel_uid32_t mount_uid; 43 44 if (fid == -1) { 45 fprintf(stderr, "Could not open %s: %s\n", 46 mount_point, strerror(errno)); 47 return -1; 48 } 49 50 if (ioctl(fid, SMB_IOC_GETMOUNTUID32, &mount_uid) != 0) { 51 __kernel_uid_t mount_uid16; 52 if (ioctl(fid, SMB_IOC_GETMOUNTUID, &mount_uid16) != 0) { 53 fprintf(stderr, "%s probably not smb-filesystem\n", 54 mount_point); 55 return -1; 56 } 57 mount_uid = mount_uid16; 58 } 59 60 if ((getuid() != 0) 61 && (mount_uid != getuid())) { 62 fprintf(stderr, "You are not allowed to umount %s\n", 63 mount_point); 64 return -1; 65 } 66 67 close(fid); 68 return 0; 69} 70 71/* Make a canonical pathname from PATH. Returns a freshly malloced string. 72 It is up the *caller* to ensure that the PATH is sensible. i.e. 73 canonicalize ("/dev/fd0/.") returns "/dev/fd0" even though ``/dev/fd0/.'' 74 is not a legal pathname for ``/dev/fd0'' Anything we cannot parse 75 we return unmodified. */ 76static char * 77canonicalize (char *path) 78{ 79 char *canonical = malloc (PATH_MAX + 1); 80 81 if (!canonical) { 82 fprintf(stderr, "Error! Not enough memory!\n"); 83 return NULL; 84 } 85 86 if (strlen(path) > PATH_MAX) { 87 fprintf(stderr, "Mount point string too long\n"); 88 return NULL; 89 } 90 91 if (path == NULL) 92 return NULL; 93 94 if (realpath (path, canonical)) 95 return canonical; 96 97 strncpy (canonical, path, PATH_MAX); 98 canonical[PATH_MAX] = '\0'; 99 return canonical; 100} 101 102 103int 104main(int argc, char *argv[]) 105{ 106 int fd; 107 char* mount_point; 108 struct mntent *mnt; 109 FILE* mtab; 110 FILE* new_mtab; 111 112 if (argc != 2) { 113 usage(); 114 exit(1); 115 } 116 117 if (geteuid() != 0) { 118 fprintf(stderr, "smbumount must be installed suid root\n"); 119 exit(1); 120 } 121 122 mount_point = canonicalize(argv[1]); 123 124 if (mount_point == NULL) 125 { 126 exit(1); 127 } 128 129 if (umount_ok(mount_point) != 0) { 130 exit(1); 131 } 132 133 if (umount(mount_point) != 0) { 134 fprintf(stderr, "Could not umount %s: %s\n", 135 mount_point, strerror(errno)); 136 exit(1); 137 } 138 139 if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1) 140 { 141 fprintf(stderr, "Can't get "MOUNTED"~ lock file"); 142 return 1; 143 } 144 close(fd); 145 146 if ((mtab = setmntent(MOUNTED, "r")) == NULL) { 147 fprintf(stderr, "Can't open " MOUNTED ": %s\n", 148 strerror(errno)); 149 return 1; 150 } 151 152#define MOUNTED_TMP MOUNTED".tmp" 153 154 if ((new_mtab = setmntent(MOUNTED_TMP, "w")) == NULL) { 155 fprintf(stderr, "Can't open " MOUNTED_TMP ": %s\n", 156 strerror(errno)); 157 endmntent(mtab); 158 return 1; 159 } 160 161 while ((mnt = getmntent(mtab)) != NULL) { 162 if (strcmp(mnt->mnt_dir, mount_point) != 0) { 163 addmntent(new_mtab, mnt); 164 } 165 } 166 167 endmntent(mtab); 168 169 if (fchmod (fileno (new_mtab), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) { 170 fprintf(stderr, "Error changing mode of %s: %s\n", 171 MOUNTED_TMP, strerror(errno)); 172 exit(1); 173 } 174 175 endmntent(new_mtab); 176 177 if (rename(MOUNTED_TMP, MOUNTED) < 0) { 178 fprintf(stderr, "Cannot rename %s to %s: %s\n", 179 MOUNTED, MOUNTED_TMP, strerror(errno)); 180 exit(1); 181 } 182 183 if (unlink(MOUNTED"~") == -1) 184 { 185 fprintf(stderr, "Can't remove "MOUNTED"~"); 186 return 1; 187 } 188 189 return 0; 190} 191