1 // SPDX-License-Identifier: GPL-2.0 1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/syscalls.h> 2 #include <linux/syscalls.h> 3 #include <linux/slab.h> 3 #include <linux/slab.h> 4 #include <linux/fs.h> 4 #include <linux/fs.h> 5 #include <linux/file.h> 5 #include <linux/file.h> 6 #include <linux/mount.h> 6 #include <linux/mount.h> 7 #include <linux/namei.h> 7 #include <linux/namei.h> 8 #include <linux/exportfs.h> 8 #include <linux/exportfs.h> 9 #include <linux/fs_struct.h> 9 #include <linux/fs_struct.h> 10 #include <linux/fsnotify.h> 10 #include <linux/fsnotify.h> 11 #include <linux/personality.h> 11 #include <linux/personality.h> 12 #include <linux/uaccess.h> 12 #include <linux/uaccess.h> 13 #include <linux/compat.h> 13 #include <linux/compat.h> 14 #include "internal.h" 14 #include "internal.h" 15 #include "mount.h" 15 #include "mount.h" 16 16 17 static long do_sys_name_to_handle(const struct 17 static long do_sys_name_to_handle(const struct path *path, 18 struct file_ 18 struct file_handle __user *ufh, 19 void __user !! 19 int __user *mnt_id, int fh_flags) 20 int fh_flags << 21 { 20 { 22 long retval; 21 long retval; 23 struct file_handle f_handle; 22 struct file_handle f_handle; 24 int handle_dwords, handle_bytes; 23 int handle_dwords, handle_bytes; 25 struct file_handle *handle = NULL; 24 struct file_handle *handle = NULL; 26 25 27 /* 26 /* 28 * We need to make sure whether the fi 27 * We need to make sure whether the file system support decoding of 29 * the file handle if decodeable file 28 * the file handle if decodeable file handle was requested. >> 29 * Otherwise, even empty export_operations are sufficient to opt-in >> 30 * to encoding FIDs. 30 */ 31 */ 31 if (!exportfs_can_encode_fh(path->dent !! 32 if (!path->dentry->d_sb->s_export_op || >> 33 (!(fh_flags & EXPORT_FH_FID) && >> 34 !path->dentry->d_sb->s_export_op->fh_to_dentry)) 32 return -EOPNOTSUPP; 35 return -EOPNOTSUPP; 33 36 34 if (copy_from_user(&f_handle, ufh, siz 37 if (copy_from_user(&f_handle, ufh, sizeof(struct file_handle))) 35 return -EFAULT; 38 return -EFAULT; 36 39 37 if (f_handle.handle_bytes > MAX_HANDLE 40 if (f_handle.handle_bytes > MAX_HANDLE_SZ) 38 return -EINVAL; 41 return -EINVAL; 39 42 40 handle = kzalloc(struct_size(handle, f !! 43 handle = kmalloc(sizeof(struct file_handle) + f_handle.handle_bytes, 41 GFP_KERNEL); 44 GFP_KERNEL); 42 if (!handle) 45 if (!handle) 43 return -ENOMEM; 46 return -ENOMEM; 44 47 45 /* convert handle size to multiple of 48 /* convert handle size to multiple of sizeof(u32) */ 46 handle_dwords = f_handle.handle_bytes 49 handle_dwords = f_handle.handle_bytes >> 2; 47 50 48 /* we ask for a non connectable maybe 51 /* we ask for a non connectable maybe decodeable file handle */ 49 retval = exportfs_encode_fh(path->dent 52 retval = exportfs_encode_fh(path->dentry, 50 (struct fi 53 (struct fid *)handle->f_handle, 51 &handle_dw 54 &handle_dwords, fh_flags); 52 handle->handle_type = retval; 55 handle->handle_type = retval; 53 /* convert handle size to bytes */ 56 /* convert handle size to bytes */ 54 handle_bytes = handle_dwords * sizeof( 57 handle_bytes = handle_dwords * sizeof(u32); 55 handle->handle_bytes = handle_bytes; 58 handle->handle_bytes = handle_bytes; 56 if ((handle->handle_bytes > f_handle.h 59 if ((handle->handle_bytes > f_handle.handle_bytes) || 57 (retval == FILEID_INVALID) || (ret 60 (retval == FILEID_INVALID) || (retval < 0)) { 58 /* As per old exportfs_encode_ 61 /* As per old exportfs_encode_fh documentation 59 * we could return ENOSPC to i 62 * we could return ENOSPC to indicate overflow 60 * But file system returned 25 63 * But file system returned 255 always. So handle 61 * both the values 64 * both the values 62 */ 65 */ 63 if (retval == FILEID_INVALID | 66 if (retval == FILEID_INVALID || retval == -ENOSPC) 64 retval = -EOVERFLOW; 67 retval = -EOVERFLOW; 65 /* 68 /* 66 * set the handle size to zero 69 * set the handle size to zero so we copy only 67 * non variable part of the fi 70 * non variable part of the file_handle 68 */ 71 */ 69 handle_bytes = 0; 72 handle_bytes = 0; 70 } else 73 } else 71 retval = 0; 74 retval = 0; 72 /* copy the mount id */ 75 /* copy the mount id */ 73 if (unique_mntid) { !! 76 if (put_user(real_mount(path->mnt)->mnt_id, mnt_id) || 74 if (put_user(real_mount(path-> !! 77 copy_to_user(ufh, handle, 75 (u64 __user *) mn !! 78 sizeof(struct file_handle) + handle_bytes)) 76 retval = -EFAULT; << 77 } else { << 78 if (put_user(real_mount(path-> << 79 (int __user *) mn << 80 retval = -EFAULT; << 81 } << 82 /* copy the handle */ << 83 if (retval != -EFAULT && << 84 copy_to_user(ufh, handle, << 85 struct_size(handl << 86 retval = -EFAULT; 79 retval = -EFAULT; 87 kfree(handle); 80 kfree(handle); 88 return retval; 81 return retval; 89 } 82 } 90 83 91 /** 84 /** 92 * sys_name_to_handle_at: convert name to hand 85 * sys_name_to_handle_at: convert name to handle 93 * @dfd: directory relative to which name is i 86 * @dfd: directory relative to which name is interpreted if not absolute 94 * @name: name that should be converted to han 87 * @name: name that should be converted to handle. 95 * @handle: resulting file handle 88 * @handle: resulting file handle 96 * @mnt_id: mount id of the file system contai 89 * @mnt_id: mount id of the file system containing the file 97 * (u64 if AT_HANDLE_MNT_ID_UNIQUE, o << 98 * @flag: flag value to indicate whether to fo 90 * @flag: flag value to indicate whether to follow symlink or not 99 * and whether a decodable file handle 91 * and whether a decodable file handle is required. 100 * 92 * 101 * @handle->handle_size indicate the space ava 93 * @handle->handle_size indicate the space available to store the 102 * variable part of the file handle in bytes. 94 * variable part of the file handle in bytes. If there is not 103 * enough space, the field is updated to retur 95 * enough space, the field is updated to return the minimum 104 * value required. 96 * value required. 105 */ 97 */ 106 SYSCALL_DEFINE5(name_to_handle_at, int, dfd, c 98 SYSCALL_DEFINE5(name_to_handle_at, int, dfd, const char __user *, name, 107 struct file_handle __user *, h !! 99 struct file_handle __user *, handle, int __user *, mnt_id, 108 int, flag) 100 int, flag) 109 { 101 { 110 struct path path; 102 struct path path; 111 int lookup_flags; 103 int lookup_flags; 112 int fh_flags; 104 int fh_flags; 113 int err; 105 int err; 114 106 115 if (flag & ~(AT_SYMLINK_FOLLOW | AT_EM !! 107 if (flag & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH | AT_HANDLE_FID)) 116 AT_HANDLE_MNT_ID_UNIQUE)) << 117 return -EINVAL; 108 return -EINVAL; 118 109 119 lookup_flags = (flag & AT_SYMLINK_FOLL 110 lookup_flags = (flag & AT_SYMLINK_FOLLOW) ? LOOKUP_FOLLOW : 0; 120 fh_flags = (flag & AT_HANDLE_FID) ? EX 111 fh_flags = (flag & AT_HANDLE_FID) ? EXPORT_FH_FID : 0; 121 if (flag & AT_EMPTY_PATH) 112 if (flag & AT_EMPTY_PATH) 122 lookup_flags |= LOOKUP_EMPTY; 113 lookup_flags |= LOOKUP_EMPTY; 123 err = user_path_at(dfd, name, lookup_f 114 err = user_path_at(dfd, name, lookup_flags, &path); 124 if (!err) { 115 if (!err) { 125 err = do_sys_name_to_handle(&p !! 116 err = do_sys_name_to_handle(&path, handle, mnt_id, fh_flags); 126 fl << 127 fh << 128 path_put(&path); 117 path_put(&path); 129 } 118 } 130 return err; 119 return err; 131 } 120 } 132 121 133 static int get_path_from_fd(int fd, struct pat !! 122 static struct vfsmount *get_vfsmount_from_fd(int fd) 134 { 123 { >> 124 struct vfsmount *mnt; >> 125 135 if (fd == AT_FDCWD) { 126 if (fd == AT_FDCWD) { 136 struct fs_struct *fs = current 127 struct fs_struct *fs = current->fs; 137 spin_lock(&fs->lock); 128 spin_lock(&fs->lock); 138 *root = fs->pwd; !! 129 mnt = mntget(fs->pwd.mnt); 139 path_get(root); << 140 spin_unlock(&fs->lock); 130 spin_unlock(&fs->lock); 141 } else { 131 } else { 142 struct fd f = fdget(fd); 132 struct fd f = fdget(fd); 143 if (!fd_file(f)) !! 133 if (!f.file) 144 return -EBADF; !! 134 return ERR_PTR(-EBADF); 145 *root = fd_file(f)->f_path; !! 135 mnt = mntget(f.file->f_path.mnt); 146 path_get(root); << 147 fdput(f); 136 fdput(f); 148 } 137 } 149 !! 138 return mnt; 150 return 0; << 151 } 139 } 152 140 153 enum handle_to_path_flags { << 154 HANDLE_CHECK_PERMS = (1 << 0), << 155 HANDLE_CHECK_SUBTREE = (1 << 1), << 156 }; << 157 << 158 struct handle_to_path_ctx { << 159 struct path root; << 160 enum handle_to_path_flags flags; << 161 unsigned int fh_flags; << 162 }; << 163 << 164 static int vfs_dentry_acceptable(void *context 141 static int vfs_dentry_acceptable(void *context, struct dentry *dentry) 165 { 142 { 166 struct handle_to_path_ctx *ctx = conte !! 143 return 1; 167 struct user_namespace *user_ns = curre << 168 struct dentry *d, *root = ctx->root.de << 169 struct mnt_idmap *idmap = mnt_idmap(ct << 170 int retval = 0; << 171 << 172 if (!root) << 173 return 1; << 174 << 175 /* Old permission model with global CA << 176 if (!ctx->flags) << 177 return 1; << 178 << 179 /* << 180 * It's racy as we're not taking renam << 181 * permissions and we just need an app << 182 * to follow a path to the file. << 183 * << 184 * It's also potentially expensive on << 185 * there is a deep path. << 186 */ << 187 d = dget(dentry); << 188 while (d != root && !IS_ROOT(d)) { << 189 struct dentry *parent = dget_p << 190 << 191 /* << 192 * We know that we have the ab << 193 * as we've verified this earl << 194 * we also need to make sure t << 195 * inodes in the path that wou << 196 * file. << 197 */ << 198 if (!privileged_wrt_inode_uidg << 199 << 200 dput(d); << 201 dput(parent); << 202 return retval; << 203 } << 204 << 205 dput(d); << 206 d = parent; << 207 } << 208 << 209 if (!(ctx->flags & HANDLE_CHECK_SUBTRE << 210 retval = 1; << 211 WARN_ON_ONCE(d != root && d != root->d << 212 dput(d); << 213 return retval; << 214 } 144 } 215 145 216 static int do_handle_to_path(struct file_handl !! 146 static int do_handle_to_path(int mountdirfd, struct file_handle *handle, 217 struct handle_to_ !! 147 struct path *path) 218 { 148 { >> 149 int retval = 0; 219 int handle_dwords; 150 int handle_dwords; 220 struct vfsmount *mnt = ctx->root.mnt; << 221 151 >> 152 path->mnt = get_vfsmount_from_fd(mountdirfd); >> 153 if (IS_ERR(path->mnt)) { >> 154 retval = PTR_ERR(path->mnt); >> 155 goto out_err; >> 156 } 222 /* change the handle size to multiple 157 /* change the handle size to multiple of sizeof(u32) */ 223 handle_dwords = handle->handle_bytes > 158 handle_dwords = handle->handle_bytes >> 2; 224 path->dentry = exportfs_decode_fh_raw( !! 159 path->dentry = exportfs_decode_fh(path->mnt, 225 (str 160 (struct fid *)handle->f_handle, 226 hand 161 handle_dwords, handle->handle_type, 227 ctx- !! 162 vfs_dentry_acceptable, NULL); 228 vfs_ !! 163 if (IS_ERR(path->dentry)) { 229 if (IS_ERR_OR_NULL(path->dentry)) { !! 164 retval = PTR_ERR(path->dentry); 230 if (path->dentry == ERR_PTR(-E !! 165 goto out_mnt; 231 return -ENOMEM; << 232 return -ESTALE; << 233 } 166 } 234 path->mnt = mntget(mnt); << 235 return 0; 167 return 0; 236 } !! 168 out_mnt: 237 !! 169 mntput(path->mnt); 238 /* !! 170 out_err: 239 * Allow relaxed permissions of file handles i !! 171 return retval; 240 * ability to mount the filesystem or create a << 241 * provided @mountdirfd. << 242 * << 243 * In both cases the caller may be able to get << 244 * the encoded file handle. If the caller is o << 245 * bind-mount we need to verify that there are << 246 * of it that could prevent us from getting to << 247 * << 248 * In principle, locked mounts can prevent the << 249 * filesystem but that only applies to procfs << 250 * support decoding file handles. << 251 */ << 252 static inline bool may_decode_fh(struct handle << 253 unsigned int << 254 { << 255 struct path *root = &ctx->root; << 256 << 257 /* << 258 * Restrict to O_DIRECTORY to provide << 259 * confusing api in the face of discon << 260 * << 261 * There's only one dentry for each di << 262 */ << 263 if (!(o_flags & O_DIRECTORY)) << 264 return false; << 265 << 266 if (ns_capable(root->mnt->mnt_sb->s_us << 267 ctx->flags = HANDLE_CHECK_PERM << 268 else if (is_mounted(root->mnt) && << 269 ns_capable(real_mount(root->m << 270 CAP_SYS_ADMIN) && << 271 !has_locked_children(real_mou << 272 ctx->flags = HANDLE_CHECK_PERM << 273 else << 274 return false; << 275 << 276 /* Are we able to override DAC permiss << 277 if (!ns_capable(current_user_ns(), CAP << 278 return false; << 279 << 280 ctx->fh_flags = EXPORT_FH_DIR_ONLY; << 281 return true; << 282 } 172 } 283 173 284 static int handle_to_path(int mountdirfd, stru 174 static int handle_to_path(int mountdirfd, struct file_handle __user *ufh, 285 struct path *path, unsigned !! 175 struct path *path) 286 { 176 { 287 int retval = 0; 177 int retval = 0; 288 struct file_handle f_handle; 178 struct file_handle f_handle; 289 struct file_handle *handle = NULL; 179 struct file_handle *handle = NULL; 290 struct handle_to_path_ctx ctx = {}; << 291 << 292 retval = get_path_from_fd(mountdirfd, << 293 if (retval) << 294 goto out_err; << 295 180 296 if (!capable(CAP_DAC_READ_SEARCH) && ! !! 181 /* >> 182 * With handle we don't look at the execute bit on the >> 183 * directory. Ideally we would like CAP_DAC_SEARCH. >> 184 * But we don't have that >> 185 */ >> 186 if (!capable(CAP_DAC_READ_SEARCH)) { 297 retval = -EPERM; 187 retval = -EPERM; 298 goto out_path; !! 188 goto out_err; 299 } 189 } 300 << 301 if (copy_from_user(&f_handle, ufh, siz 190 if (copy_from_user(&f_handle, ufh, sizeof(struct file_handle))) { 302 retval = -EFAULT; 191 retval = -EFAULT; 303 goto out_path; !! 192 goto out_err; 304 } 193 } 305 if ((f_handle.handle_bytes > MAX_HANDL 194 if ((f_handle.handle_bytes > MAX_HANDLE_SZ) || 306 (f_handle.handle_bytes == 0)) { 195 (f_handle.handle_bytes == 0)) { 307 retval = -EINVAL; 196 retval = -EINVAL; 308 goto out_path; !! 197 goto out_err; 309 } 198 } 310 handle = kmalloc(struct_size(handle, f !! 199 handle = kmalloc(sizeof(struct file_handle) + f_handle.handle_bytes, 311 GFP_KERNEL); 200 GFP_KERNEL); 312 if (!handle) { 201 if (!handle) { 313 retval = -ENOMEM; 202 retval = -ENOMEM; 314 goto out_path; !! 203 goto out_err; 315 } 204 } 316 /* copy the full handle */ 205 /* copy the full handle */ 317 *handle = f_handle; 206 *handle = f_handle; 318 if (copy_from_user(&handle->f_handle, 207 if (copy_from_user(&handle->f_handle, 319 &ufh->f_handle, 208 &ufh->f_handle, 320 f_handle.handle_byt 209 f_handle.handle_bytes)) { 321 retval = -EFAULT; 210 retval = -EFAULT; 322 goto out_handle; 211 goto out_handle; 323 } 212 } 324 213 325 retval = do_handle_to_path(handle, pat !! 214 retval = do_handle_to_path(mountdirfd, handle, path); 326 215 327 out_handle: 216 out_handle: 328 kfree(handle); 217 kfree(handle); 329 out_path: << 330 path_put(&ctx.root); << 331 out_err: 218 out_err: 332 return retval; 219 return retval; 333 } 220 } 334 221 335 static long do_handle_open(int mountdirfd, str 222 static long do_handle_open(int mountdirfd, struct file_handle __user *ufh, 336 int open_flag) 223 int open_flag) 337 { 224 { 338 long retval = 0; 225 long retval = 0; 339 struct path path; 226 struct path path; 340 struct file *file; 227 struct file *file; 341 int fd; 228 int fd; 342 229 343 retval = handle_to_path(mountdirfd, uf !! 230 retval = handle_to_path(mountdirfd, ufh, &path); 344 if (retval) 231 if (retval) 345 return retval; 232 return retval; 346 233 347 fd = get_unused_fd_flags(open_flag); 234 fd = get_unused_fd_flags(open_flag); 348 if (fd < 0) { 235 if (fd < 0) { 349 path_put(&path); 236 path_put(&path); 350 return fd; 237 return fd; 351 } 238 } 352 file = file_open_root(&path, "", open_ 239 file = file_open_root(&path, "", open_flag, 0); 353 if (IS_ERR(file)) { 240 if (IS_ERR(file)) { 354 put_unused_fd(fd); 241 put_unused_fd(fd); 355 retval = PTR_ERR(file); 242 retval = PTR_ERR(file); 356 } else { 243 } else { 357 retval = fd; 244 retval = fd; 358 fd_install(fd, file); 245 fd_install(fd, file); 359 } 246 } 360 path_put(&path); 247 path_put(&path); 361 return retval; 248 return retval; 362 } 249 } 363 250 364 /** 251 /** 365 * sys_open_by_handle_at: Open the file handle 252 * sys_open_by_handle_at: Open the file handle 366 * @mountdirfd: directory file descriptor 253 * @mountdirfd: directory file descriptor 367 * @handle: file handle to be opened 254 * @handle: file handle to be opened 368 * @flags: open flags. 255 * @flags: open flags. 369 * 256 * 370 * @mountdirfd indicate the directory file des 257 * @mountdirfd indicate the directory file descriptor 371 * of the mount point. file handle is decoded 258 * of the mount point. file handle is decoded relative 372 * to the vfsmount pointed by the @mountdirfd. 259 * to the vfsmount pointed by the @mountdirfd. @flags 373 * value is same as the open(2) flags. 260 * value is same as the open(2) flags. 374 */ 261 */ 375 SYSCALL_DEFINE3(open_by_handle_at, int, mountd 262 SYSCALL_DEFINE3(open_by_handle_at, int, mountdirfd, 376 struct file_handle __user *, h 263 struct file_handle __user *, handle, 377 int, flags) 264 int, flags) 378 { 265 { 379 long ret; 266 long ret; 380 267 381 if (force_o_largefile()) 268 if (force_o_largefile()) 382 flags |= O_LARGEFILE; 269 flags |= O_LARGEFILE; 383 270 384 ret = do_handle_open(mountdirfd, handl 271 ret = do_handle_open(mountdirfd, handle, flags); 385 return ret; 272 return ret; 386 } 273 } 387 274 388 #ifdef CONFIG_COMPAT 275 #ifdef CONFIG_COMPAT 389 /* 276 /* 390 * Exactly like fs/open.c:sys_open_by_handle_a 277 * Exactly like fs/open.c:sys_open_by_handle_at(), except that it 391 * doesn't set the O_LARGEFILE flag. 278 * doesn't set the O_LARGEFILE flag. 392 */ 279 */ 393 COMPAT_SYSCALL_DEFINE3(open_by_handle_at, int, 280 COMPAT_SYSCALL_DEFINE3(open_by_handle_at, int, mountdirfd, 394 struct file_handl 281 struct file_handle __user *, handle, int, flags) 395 { 282 { 396 return do_handle_open(mountdirfd, hand 283 return do_handle_open(mountdirfd, handle, flags); 397 } 284 } 398 #endif 285 #endif 399 286
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.