| 1 | |
| 2 | #include <linux/syscalls.h>
|
| 3 | #include <linux/slab.h>
|
| 4 | #include <linux/fs.h>
|
| 5 | #include <linux/file.h>
|
| 6 | #include <linux/mount.h>
|
| 7 | #include <linux/namei.h>
|
| 8 | #include <linux/exportfs.h>
|
| 9 | #include <linux/fs_struct.h>
|
| 10 | #include <linux/fsnotify.h>
|
| 11 | #include <linux/personality.h>
|
| 12 | #include <linux/uaccess.h>
|
| 13 | #include <linux/compat.h>
|
| 14 | #include <linux/nsfs.h>
|
| 15 | #include "internal.h"
|
| 16 | #include "mount.h"
|
| 17 |
|
| 18 | static long do_sys_name_to_handle(const struct path *path,
|
| 19 | struct file_handle __user *ufh,
|
| 20 | void __user *mnt_id, bool unique_mntid,
|
| 21 | int fh_flags)
|
| 22 | {
|
| 23 | long retval;
|
| 24 | struct file_handle f_handle;
|
| 25 | int handle_dwords, handle_bytes;
|
| 26 | struct file_handle *handle = NULL;
|
| 27 |
|
| 28 | |
| 29 | * We need to make sure whether the file system support decoding of
|
| 30 | * the file handle if decodeable file handle was requested.
|
| 31 |
|
| 32 | if (!exportfs_can_encode_fh(path->dentry->d_sb->s_export_op, fh_flags))
|
| 33 | return -EOPNOTSUPP;
|
| 34 |
|
| 35 | |
| 36 | * A request to encode a connectable handle for a disconnected dentry
|
| 37 | * is unexpected since AT_EMPTY_PATH is not allowed.
|
| 38 |
|
| 39 | if (fh_flags & EXPORT_FH_CONNECTABLE &&
|
| 40 | WARN_ON(path->dentry->d_flags & DCACHE_DISCONNECTED))
|
| 41 | return -EINVAL;
|
| 42 |
|
| 43 | if (copy_from_user(&f_handle, ufh, sizeof(struct file_handle)))
|
| 44 | return -EFAULT;
|
| 45 |
|
| 46 | if (f_handle.handle_bytes > MAX_HANDLE_SZ)
|
| 47 | return -EINVAL;
|
| 48 |
|
| 49 | handle = kzalloc_flex(*handle, f_handle, f_handle.handle_bytes);
|
| 50 | if (!handle)
|
| 51 | return -ENOMEM;
|
| 52 |
|
| 53 |
|
| 54 | handle_dwords = f_handle.handle_bytes >> 2;
|
| 55 |
|
| 56 |
|
| 57 | retval = exportfs_encode_fh(path->dentry,
|
| 58 | (struct fid *)handle->f_handle,
|
| 59 | &handle_dwords, fh_flags);
|
| 60 | handle->handle_type = retval;
|
| 61 |
|
| 62 | handle_bytes = handle_dwords * sizeof(u32);
|
| 63 | handle->handle_bytes = handle_bytes;
|
| 64 | if ((handle->handle_bytes > f_handle.handle_bytes) ||
|
| 65 | (retval == FILEID_INVALID) || (retval < 0)) {
|
| 66 | |
| 67 | * we could return ENOSPC to indicate overflow
|
| 68 | * But file system returned 255 always. So handle
|
| 69 | * both the values
|
| 70 |
|
| 71 | if (retval == FILEID_INVALID || retval == -ENOSPC)
|
| 72 | retval = -EOVERFLOW;
|
| 73 | |
| 74 | * set the handle size to zero so we copy only
|
| 75 | * non variable part of the file_handle
|
| 76 |
|
| 77 | handle_bytes = 0;
|
| 78 | } else {
|
| 79 | |
| 80 | * When asked to encode a connectable file handle, encode this
|
| 81 | * property in the file handle itself, so that we later know
|
| 82 | * how to decode it.
|
| 83 | * For sanity, also encode in the file handle if the encoded
|
| 84 | * object is a directory and verify this during decode, because
|
| 85 | * decoding directory file handles is quite different than
|
| 86 | * decoding connectable non-directory file handles.
|
| 87 |
|
| 88 | if (fh_flags & EXPORT_FH_CONNECTABLE) {
|
| 89 | handle->handle_type |= FILEID_IS_CONNECTABLE;
|
| 90 | if (d_is_dir(path->dentry))
|
| 91 | handle->handle_type |= FILEID_IS_DIR;
|
| 92 | }
|
| 93 | retval = 0;
|
| 94 | }
|
| 95 |
|
| 96 | if (unique_mntid) {
|
| 97 | if (put_user(real_mount(path->mnt)->mnt_id_unique,
|
| 98 | (u64 __user *) mnt_id))
|
| 99 | retval = -EFAULT;
|
| 100 | } else {
|
| 101 | if (put_user(real_mount(path->mnt)->mnt_id,
|
| 102 | (int __user *) mnt_id))
|
| 103 | retval = -EFAULT;
|
| 104 | }
|
| 105 |
|
| 106 | if (retval != -EFAULT &&
|
| 107 | copy_to_user(ufh, handle,
|
| 108 | struct_size(handle, f_handle, handle_bytes)))
|
| 109 | retval = -EFAULT;
|
| 110 | kfree(handle);
|
| 111 | return retval;
|
| 112 | }
|
| 113 |
|
| 114 | |
| 115 | * sys_name_to_handle_at: convert name to handle
|
| 116 | * @dfd: directory relative to which name is interpreted if not absolute
|
| 117 | * @name: name that should be converted to handle.
|
| 118 | * @handle: resulting file handle
|
| 119 | * @mnt_id: mount id of the file system containing the file
|
| 120 | * (u64 if AT_HANDLE_MNT_ID_UNIQUE, otherwise int)
|
| 121 | * @flag: flag value to indicate whether to follow symlink or not
|
| 122 | * and whether a decodable file handle is required.
|
| 123 | *
|
| 124 | * @handle->handle_size indicate the space available to store the
|
| 125 | * variable part of the file handle in bytes. If there is not
|
| 126 | * enough space, the field is updated to return the minimum
|
| 127 | * value required.
|
| 128 |
|
| 129 | SYSCALL_DEFINE5(name_to_handle_at, int, dfd, const char __user *, name,
|
| 130 | struct file_handle __user *, handle, void __user *, mnt_id,
|
| 131 | int, flag)
|
| 132 | {
|
| 133 | struct path path;
|
| 134 | int lookup_flags;
|
| 135 | int fh_flags = 0;
|
| 136 | int err;
|
| 137 |
|
| 138 | if (flag & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH | AT_HANDLE_FID |
|
| 139 | AT_HANDLE_MNT_ID_UNIQUE | AT_HANDLE_CONNECTABLE))
|
| 140 | return -EINVAL;
|
| 141 |
|
| 142 | |
| 143 | * AT_HANDLE_FID means there is no intention to decode file handle
|
| 144 | * AT_HANDLE_CONNECTABLE means there is an intention to decode a
|
| 145 | * connected fd (with known path), so these flags are conflicting.
|
| 146 | * AT_EMPTY_PATH could be used along with a dfd that refers to a
|
| 147 | * disconnected non-directory, which cannot be used to encode a
|
| 148 | * connectable file handle, because its parent is unknown.
|
| 149 |
|
| 150 | if (flag & AT_HANDLE_CONNECTABLE &&
|
| 151 | flag & (AT_HANDLE_FID | AT_EMPTY_PATH))
|
| 152 | return -EINVAL;
|
| 153 | else if (flag & AT_HANDLE_FID)
|
| 154 | fh_flags |= EXPORT_FH_FID;
|
| 155 | else if (flag & AT_HANDLE_CONNECTABLE)
|
| 156 | fh_flags |= EXPORT_FH_CONNECTABLE;
|
| 157 |
|
| 158 | lookup_flags = (flag & AT_SYMLINK_FOLLOW) ? LOOKUP_FOLLOW : 0;
|
| 159 | CLASS(filename_uflags, filename)(name, flag);
|
| 160 | err = filename_lookup(dfd, filename, lookup_flags, &path, NULL);
|
| 161 | if (!err) {
|
| 162 | err = do_sys_name_to_handle(&path, handle, mnt_id,
|
| 163 | flag & AT_HANDLE_MNT_ID_UNIQUE,
|
| 164 | fh_flags);
|
| 165 | path_put(&path);
|
| 166 | }
|
| 167 | return err;
|
| 168 | }
|
| 169 |
|
| 170 | static int get_path_anchor(int fd, struct path *root)
|
| 171 | {
|
| 172 | if (fd >= 0) {
|
| 173 | CLASS(fd, f)(fd);
|
| 174 | if (fd_empty(f))
|
| 175 | return -EBADF;
|
| 176 | *root = fd_file(f)->f_path;
|
| 177 | path_get(root);
|
| 178 | return 0;
|
| 179 | }
|
| 180 |
|
| 181 | if (fd == AT_FDCWD) {
|
| 182 | get_fs_pwd(current->fs, root);
|
| 183 | return 0;
|
| 184 | }
|
| 185 |
|
| 186 | if (fd == FD_PIDFS_ROOT) {
|
| 187 | pidfs_get_root(root);
|
| 188 | return 0;
|
| 189 | }
|
| 190 |
|
| 191 | if (fd == FD_NSFS_ROOT) {
|
| 192 | nsfs_get_root(root);
|
| 193 | return 0;
|
| 194 | }
|
| 195 |
|
| 196 | return -EBADF;
|
| 197 | }
|
| 198 |
|
| 199 | static int vfs_dentry_acceptable(void *context, struct dentry *dentry)
|
| 200 | {
|
| 201 | struct handle_to_path_ctx *ctx = context;
|
| 202 | struct user_namespace *user_ns = current_user_ns();
|
| 203 | struct dentry *d, *root = ctx->root.dentry;
|
| 204 | const struct mnt_idmap *idmap = mnt_idmap(ctx->root.mnt);
|
| 205 | int retval = 0;
|
| 206 |
|
| 207 | if (!root)
|
| 208 | return 1;
|
| 209 |
|
| 210 |
|
| 211 | if (!ctx->flags)
|
| 212 | return 1;
|
| 213 |
|
| 214 | |
| 215 | * Verify that the decoded dentry itself has a valid id mapping.
|
| 216 | * In case the decoded dentry is the mountfd root itself, this
|
| 217 | * verifies that the mountfd inode itself has a valid id mapping.
|
| 218 |
|
| 219 | if (!privileged_wrt_inode_uidgid(user_ns, idmap, d_inode(dentry)))
|
| 220 | return 0;
|
| 221 |
|
| 222 | |
| 223 | * It's racy as we're not taking rename_lock but we're able to ignore
|
| 224 | * permissions and we just need an approximation whether we were able
|
| 225 | * to follow a path to the file.
|
| 226 | *
|
| 227 | * It's also potentially expensive on some filesystems especially if
|
| 228 | * there is a deep path.
|
| 229 |
|
| 230 | d = dget(dentry);
|
| 231 | while (d != root && !IS_ROOT(d)) {
|
| 232 | struct dentry *parent = dget_parent(d);
|
| 233 |
|
| 234 | |
| 235 | * We know that we have the ability to override DAC permissions
|
| 236 | * as we've verified this earlier via CAP_DAC_READ_SEARCH. But
|
| 237 | * we also need to make sure that there aren't any unmapped
|
| 238 | * inodes in the path that would prevent us from reaching the
|
| 239 | * file.
|
| 240 |
|
| 241 | if (!privileged_wrt_inode_uidgid(user_ns, idmap,
|
| 242 | d_inode(parent))) {
|
| 243 | dput(d);
|
| 244 | dput(parent);
|
| 245 | return retval;
|
| 246 | }
|
| 247 |
|
| 248 | dput(d);
|
| 249 | d = parent;
|
| 250 | }
|
| 251 |
|
| 252 | if (!(ctx->flags & HANDLE_CHECK_SUBTREE) || d == root)
|
| 253 | retval = 1;
|
| 254 | |
| 255 | * exportfs_decode_fh_raw() does not call acceptable() callback with
|
| 256 | * a disconnected directory dentry, so we should have reached either
|
| 257 | * mount fd directory or sb root.
|
| 258 |
|
| 259 | if (ctx->fh_flags & EXPORT_FH_DIR_ONLY)
|
| 260 | WARN_ON_ONCE(d != root && d != root->d_sb->s_root);
|
| 261 | dput(d);
|
| 262 | return retval;
|
| 263 | }
|
| 264 |
|
| 265 | static int do_handle_to_path(struct file_handle *handle, struct path *path,
|
| 266 | struct handle_to_path_ctx *ctx)
|
| 267 | {
|
| 268 | int handle_dwords;
|
| 269 | struct vfsmount *mnt = ctx->root.mnt;
|
| 270 | struct dentry *dentry;
|
| 271 |
|
| 272 |
|
| 273 | handle_dwords = handle->handle_bytes >> 2;
|
| 274 | dentry = exportfs_decode_fh_raw(mnt, (struct fid *)handle->f_handle,
|
| 275 | handle_dwords, handle->handle_type,
|
| 276 | ctx->fh_flags, vfs_dentry_acceptable,
|
| 277 | ctx);
|
| 278 | if (IS_ERR_OR_NULL(dentry)) {
|
| 279 | if (dentry == ERR_PTR(-ENOMEM))
|
| 280 | return -ENOMEM;
|
| 281 | return -ESTALE;
|
| 282 | }
|
| 283 | path->dentry = dentry;
|
| 284 | path->mnt = mntget(mnt);
|
| 285 | return 0;
|
| 286 | }
|
| 287 |
|
| 288 | static bool capable_wrt_mount(struct mount *mount)
|
| 289 | {
|
| 290 | struct mnt_namespace *mnt_ns;
|
| 291 |
|
| 292 | |
| 293 | * For ->mnt_ns access.
|
| 294 | * The following READ_ONCE() is semantically rcu_dereference().
|
| 295 |
|
| 296 | guard(rcu)();
|
| 297 | mnt_ns = READ_ONCE(mount->mnt_ns);
|
| 298 | return mnt_ns && ns_capable(mnt_ns->user_ns, CAP_SYS_ADMIN);
|
| 299 | }
|
| 300 |
|
| 301 | |
| 302 | * Does the caller have an unobstructed way to everything below @root? Only
|
| 303 | * if the mount is mounted, the caller is privileged over its mount namespace
|
| 304 | * and no locked child covers something below @root->dentry. One answer from
|
| 305 | * under mount_lock: an umount in between clears ->mnt_ns and takes the
|
| 306 | * children off the mount, the locked ones too.
|
| 307 |
|
| 308 | static bool subtree_unobstructed(const struct path *root)
|
| 309 | {
|
| 310 | struct mount *mnt = real_mount(root->mnt);
|
| 311 |
|
| 312 | guard(mount_locked_reader)();
|
| 313 | return is_mounted(root->mnt) && capable_wrt_mount(mnt) &&
|
| 314 | !has_locked_children(mnt, root->dentry);
|
| 315 | }
|
| 316 |
|
| 317 | static inline int may_decode_fh(struct handle_to_path_ctx *ctx,
|
| 318 | unsigned int o_flags)
|
| 319 | {
|
| 320 | struct path *root = &ctx->root;
|
| 321 |
|
| 322 | if (capable(CAP_DAC_READ_SEARCH))
|
| 323 | return 0;
|
| 324 |
|
| 325 | |
| 326 | * Allow relaxed permissions of file handles if the caller has
|
| 327 | * the ability to mount the filesystem or create a bind-mount of
|
| 328 | * the provided @mountdirfd.
|
| 329 | *
|
| 330 | * In both cases the caller may be able to get an unobstructed
|
| 331 | * way to the encoded file handle. If the caller is only able to
|
| 332 | * create a bind-mount we need to verify that there are no
|
| 333 | * locked mounts on top of it that could prevent us from getting
|
| 334 | * to the encoded file.
|
| 335 | *
|
| 336 | * In principle, locked mounts can prevent the caller from
|
| 337 | * mounting the filesystem but that only applies to procfs and
|
| 338 | * sysfs neither of which support decoding file handles.
|
| 339 | *
|
| 340 | * Restrict to O_DIRECTORY to provide a deterministic API that
|
| 341 | * avoids a confusing api in the face of disconnected non-dir
|
| 342 | * dentries.
|
| 343 | *
|
| 344 | * There's only one dentry for each directory inode (VFS rule)...
|
| 345 |
|
| 346 | if (!(o_flags & O_DIRECTORY))
|
| 347 | return -EPERM;
|
| 348 |
|
| 349 | if (ns_capable(root->mnt->mnt_sb->s_user_ns, CAP_SYS_ADMIN))
|
| 350 | ctx->flags = HANDLE_CHECK_PERMS;
|
| 351 | else if (subtree_unobstructed(root))
|
| 352 | ctx->flags = HANDLE_CHECK_PERMS | HANDLE_CHECK_SUBTREE;
|
| 353 | else
|
| 354 | return -EPERM;
|
| 355 |
|
| 356 |
|
| 357 | if (!ns_capable(current_user_ns(), CAP_DAC_READ_SEARCH))
|
| 358 | return -EPERM;
|
| 359 |
|
| 360 | ctx->fh_flags = EXPORT_FH_DIR_ONLY;
|
| 361 | return 0;
|
| 362 | }
|
| 363 |
|
| 364 | static int handle_to_path(int mountdirfd, struct file_handle __user *ufh,
|
| 365 | struct path *path, unsigned int o_flags)
|
| 366 | {
|
| 367 | int retval = 0;
|
| 368 | struct file_handle f_handle;
|
| 369 | struct file_handle *handle __free(kfree) = NULL;
|
| 370 | struct handle_to_path_ctx ctx = {};
|
| 371 | const struct export_operations *eops;
|
| 372 |
|
| 373 | if (copy_from_user(&f_handle, ufh, sizeof(struct file_handle)))
|
| 374 | return -EFAULT;
|
| 375 |
|
| 376 | if ((f_handle.handle_bytes > MAX_HANDLE_SZ) ||
|
| 377 | (f_handle.handle_bytes == 0))
|
| 378 | return -EINVAL;
|
| 379 |
|
| 380 | if (f_handle.handle_type < 0 ||
|
| 381 | FILEID_USER_FLAGS(f_handle.handle_type) & ~FILEID_VALID_USER_FLAGS)
|
| 382 | return -EINVAL;
|
| 383 |
|
| 384 | retval = get_path_anchor(mountdirfd, &ctx.root);
|
| 385 | if (retval)
|
| 386 | return retval;
|
| 387 |
|
| 388 | eops = ctx.root.mnt->mnt_sb->s_export_op;
|
| 389 | if (eops && eops->permission)
|
| 390 | retval = eops->permission(&ctx, o_flags);
|
| 391 | else
|
| 392 | retval = may_decode_fh(&ctx, o_flags);
|
| 393 | if (retval)
|
| 394 | goto out_path;
|
| 395 |
|
| 396 | handle = kmalloc_flex(*handle, f_handle, f_handle.handle_bytes);
|
| 397 | if (!handle) {
|
| 398 | retval = -ENOMEM;
|
| 399 | goto out_path;
|
| 400 | }
|
| 401 |
|
| 402 | *handle = f_handle;
|
| 403 | if (copy_from_user(&handle->f_handle,
|
| 404 | &ufh->f_handle,
|
| 405 | f_handle.handle_bytes)) {
|
| 406 | retval = -EFAULT;
|
| 407 | goto out_path;
|
| 408 | }
|
| 409 |
|
| 410 | |
| 411 | * If handle was encoded with AT_HANDLE_CONNECTABLE, verify that we
|
| 412 | * are decoding an fd with connected path, which is accessible from
|
| 413 | * the mount fd path.
|
| 414 |
|
| 415 | if (f_handle.handle_type & FILEID_IS_CONNECTABLE) {
|
| 416 | ctx.fh_flags |= EXPORT_FH_CONNECTABLE;
|
| 417 | ctx.flags |= HANDLE_CHECK_SUBTREE;
|
| 418 | }
|
| 419 | if (f_handle.handle_type & FILEID_IS_DIR)
|
| 420 | ctx.fh_flags |= EXPORT_FH_DIR_ONLY;
|
| 421 |
|
| 422 | handle->handle_type &= ~FILEID_USER_FLAGS_MASK;
|
| 423 | retval = do_handle_to_path(handle, path, &ctx);
|
| 424 |
|
| 425 | out_path:
|
| 426 | path_put(&ctx.root);
|
| 427 | return retval;
|
| 428 | }
|
| 429 |
|
| 430 | static struct file *file_open_handle(struct path *path, int open_flag)
|
| 431 | {
|
| 432 | const struct export_operations *eops;
|
| 433 |
|
| 434 | eops = path->mnt->mnt_sb->s_export_op;
|
| 435 | if (eops->open)
|
| 436 | return eops->open(path, open_flag);
|
| 437 |
|
| 438 | return file_open_root(path, "", open_flag, 0);
|
| 439 | }
|
| 440 |
|
| 441 | static long do_handle_open(int mountdirfd, struct file_handle __user *ufh,
|
| 442 | int open_flag)
|
| 443 | {
|
| 444 | long retval;
|
| 445 | struct path path __free(path_put) = {};
|
| 446 |
|
| 447 | retval = handle_to_path(mountdirfd, ufh, &path, open_flag);
|
| 448 | if (retval)
|
| 449 | return retval;
|
| 450 |
|
| 451 | return FD_ADD(open_flag, file_open_handle(&path, open_flag));
|
| 452 | }
|
| 453 |
|
| 454 | |
| 455 | * sys_open_by_handle_at: Open the file handle
|
| 456 | * @mountdirfd: directory file descriptor
|
| 457 | * @handle: file handle to be opened
|
| 458 | * @flags: open flags.
|
| 459 | *
|
| 460 | * @mountdirfd indicate the directory file descriptor
|
| 461 | * of the mount point. file handle is decoded relative
|
| 462 | * to the vfsmount pointed by the @mountdirfd. @flags
|
| 463 | * value is same as the open(2) flags.
|
| 464 |
|
| 465 | SYSCALL_DEFINE3(open_by_handle_at, int, mountdirfd,
|
| 466 | struct file_handle __user *, handle,
|
| 467 | int, flags)
|
| 468 | {
|
| 469 | long ret;
|
| 470 |
|
| 471 | if (force_o_largefile())
|
| 472 | flags |= O_LARGEFILE;
|
| 473 |
|
| 474 | ret = do_handle_open(mountdirfd, handle, flags);
|
| 475 | return ret;
|
| 476 | }
|
| 477 |
|
| 478 | #ifdef CONFIG_COMPAT
|
| 479 | |
| 480 | * Exactly like fs/open.c:sys_open_by_handle_at(), except that it
|
| 481 | * doesn't set the O_LARGEFILE flag.
|
| 482 |
|
| 483 | COMPAT_SYSCALL_DEFINE3(open_by_handle_at, int, mountdirfd,
|
| 484 | struct file_handle __user *, handle, int, flags)
|
| 485 | {
|
| 486 | return do_handle_open(mountdirfd, handle, flags);
|
| 487 | }
|
| 488 | #endif
|