Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'vfs-6.17-rc3.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs

Pull vfs fixes from Christian Brauner:

- Fix two memory leaks in pidfs

- Prevent changing the idmapping of an already idmapped mount without
OPEN_TREE_CLONE through open_tree_attr()

- Don't fail listing extended attributes in kernfs when no extended
attributes are set

- Fix the return value in coredump_parse()

- Fix the error handling for unbuffered writes in netfs

- Fix broken data integrity guarantees for O_SYNC writes via iomap

- Fix UAF in __mark_inode_dirty()

- Keep inode->i_blkbits constant in fuse

- Fix coredump selftests

- Fix get_unused_fd_flags() usage in do_handle_open()

- Rename EXPORT_SYMBOL_GPL_FOR_MODULES to EXPORT_SYMBOL_FOR_MODULES

- Fix use-after-free in bh_read()

- Fix incorrect lflags value in the move_mount() syscall

* tag 'vfs-6.17-rc3.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs:
signal: Fix memory leak for PIDFD_SELF* sentinels
kernfs: don't fail listing extended attributes
coredump: Fix return value in coredump_parse()
fs/buffer: fix use-after-free when call bh_read() helper
pidfs: Fix memory leak in pidfd_info()
netfs: Fix unbuffered write error handling
fhandle: do_handle_open() should get FD with user flags
module: Rename EXPORT_SYMBOL_GPL_FOR_MODULES to EXPORT_SYMBOL_FOR_MODULES
fs: fix incorrect lflags value in the move_mount syscall
selftests/coredump: Remove the read() that fails the test
fuse: keep inode->i_blkbits constant
iomap: Fix broken data integrity guarantees for O_SYNC writes
selftests/mount_setattr: add smoke tests for open_tree_attr(2) bug
open_tree_attr: do not allow id-mapping changes without OPEN_TREE_CLONE
fs: writeback: fix use-after-free in __mark_inode_dirty()

+138 -68
+6 -5
Documentation/core-api/symbol-namespaces.rst
··· 76 76 within the corresponding compilation unit before the #include for 77 77 <linux/export.h>. Typically it's placed before the first #include statement. 78 78 79 - Using the EXPORT_SYMBOL_GPL_FOR_MODULES() macro 80 - ----------------------------------------------- 79 + Using the EXPORT_SYMBOL_FOR_MODULES() macro 80 + ------------------------------------------- 81 81 82 82 Symbols exported using this macro are put into a module namespace. This 83 - namespace cannot be imported. 83 + namespace cannot be imported. These exports are GPL-only as they are only 84 + intended for in-tree modules. 84 85 85 86 The macro takes a comma separated list of module names, allowing only those 86 87 modules to access this symbol. Simple tail-globs are supported. 87 88 88 89 For example:: 89 90 90 - EXPORT_SYMBOL_GPL_FOR_MODULES(preempt_notifier_inc, "kvm,kvm-*") 91 + EXPORT_SYMBOL_FOR_MODULES(preempt_notifier_inc, "kvm,kvm-*") 91 92 92 - will limit usage of this symbol to modules whoes name matches the given 93 + will limit usage of this symbol to modules whose name matches the given 93 94 patterns. 94 95 95 96 How to use Symbols exported in Namespaces
+4 -4
drivers/tty/serial/8250/8250_rsa.c
··· 147 147 if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) 148 148 serial_out(up, UART_RSA_FRR, 0); 149 149 } 150 - EXPORT_SYMBOL_GPL_FOR_MODULES(rsa_enable, "8250_base"); 150 + EXPORT_SYMBOL_FOR_MODULES(rsa_enable, "8250_base"); 151 151 152 152 /* 153 153 * Attempts to turn off the RSA FIFO and resets the RSA board back to 115kbps compat mode. It is ··· 179 179 up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16; 180 180 uart_port_unlock_irq(&up->port); 181 181 } 182 - EXPORT_SYMBOL_GPL_FOR_MODULES(rsa_disable, "8250_base"); 182 + EXPORT_SYMBOL_FOR_MODULES(rsa_disable, "8250_base"); 183 183 184 184 void rsa_autoconfig(struct uart_8250_port *up) 185 185 { ··· 192 192 if (__rsa_enable(up)) 193 193 up->port.type = PORT_RSA; 194 194 } 195 - EXPORT_SYMBOL_GPL_FOR_MODULES(rsa_autoconfig, "8250_base"); 195 + EXPORT_SYMBOL_FOR_MODULES(rsa_autoconfig, "8250_base"); 196 196 197 197 void rsa_reset(struct uart_8250_port *up) 198 198 { ··· 201 201 202 202 serial_out(up, UART_RSA_FRR, 0); 203 203 } 204 - EXPORT_SYMBOL_GPL_FOR_MODULES(rsa_reset, "8250_base"); 204 + EXPORT_SYMBOL_FOR_MODULES(rsa_reset, "8250_base"); 205 205 206 206 #ifdef CONFIG_SERIAL_8250_DEPRECATED_OPTIONS 207 207 #ifndef MODULE
+1 -1
fs/anon_inodes.c
··· 129 129 } 130 130 return inode; 131 131 } 132 - EXPORT_SYMBOL_GPL_FOR_MODULES(anon_inode_make_secure_inode, "kvm"); 132 + EXPORT_SYMBOL_FOR_MODULES(anon_inode_make_secure_inode, "kvm"); 133 133 134 134 static struct file *__anon_inode_getfile(const char *name, 135 135 const struct file_operations *fops,
+1 -1
fs/buffer.c
··· 157 157 */ 158 158 void end_buffer_read_sync(struct buffer_head *bh, int uptodate) 159 159 { 160 - __end_buffer_read_notouch(bh, uptodate); 161 160 put_bh(bh); 161 + __end_buffer_read_notouch(bh, uptodate); 162 162 } 163 163 EXPORT_SYMBOL(end_buffer_read_sync); 164 164
+1 -1
fs/coredump.c
··· 345 345 was_space = false; 346 346 err = cn_printf(cn, "%c", '\0'); 347 347 if (err) 348 - return err; 348 + return false; 349 349 (*argv)[(*argc)++] = cn->used; 350 350 } 351 351 }
+1 -1
fs/fhandle.c
··· 402 402 if (retval) 403 403 return retval; 404 404 405 - CLASS(get_unused_fd, fd)(O_CLOEXEC); 405 + CLASS(get_unused_fd, fd)(open_flag); 406 406 if (fd < 0) 407 407 return fd; 408 408
+5 -4
fs/fs-writeback.c
··· 2608 2608 wakeup_bdi = inode_io_list_move_locked(inode, wb, 2609 2609 dirty_list); 2610 2610 2611 - spin_unlock(&wb->list_lock); 2612 - spin_unlock(&inode->i_lock); 2613 - trace_writeback_dirty_inode_enqueue(inode); 2614 - 2615 2611 /* 2616 2612 * If this is the first dirty inode for this bdi, 2617 2613 * we have to wake-up the corresponding bdi thread ··· 2617 2621 if (wakeup_bdi && 2618 2622 (wb->bdi->capabilities & BDI_CAP_WRITEBACK)) 2619 2623 wb_wakeup_delayed(wb); 2624 + 2625 + spin_unlock(&wb->list_lock); 2626 + spin_unlock(&inode->i_lock); 2627 + trace_writeback_dirty_inode_enqueue(inode); 2628 + 2620 2629 return; 2621 2630 } 2622 2631 }
-5
fs/fuse/inode.c
··· 289 289 } 290 290 } 291 291 292 - if (attr->blksize != 0) 293 - inode->i_blkbits = ilog2(attr->blksize); 294 - else 295 - inode->i_blkbits = inode->i_sb->s_blocksize_bits; 296 - 297 292 /* 298 293 * Don't set the sticky bit in i_mode, unless we want the VFS 299 294 * to check permissions. This prevents failures due to the
+7 -7
fs/iomap/direct-io.c
··· 363 363 if (iomap->flags & IOMAP_F_SHARED) 364 364 dio->flags |= IOMAP_DIO_COW; 365 365 366 - if (iomap->flags & IOMAP_F_NEW) { 366 + if (iomap->flags & IOMAP_F_NEW) 367 367 need_zeroout = true; 368 - } else if (iomap->type == IOMAP_MAPPED) { 369 - if (iomap_dio_can_use_fua(iomap, dio)) 370 - bio_opf |= REQ_FUA; 371 - else 372 - dio->flags &= ~IOMAP_DIO_WRITE_THROUGH; 373 - } 368 + else if (iomap->type == IOMAP_MAPPED && 369 + iomap_dio_can_use_fua(iomap, dio)) 370 + bio_opf |= REQ_FUA; 371 + 372 + if (!(bio_opf & REQ_FUA)) 373 + dio->flags &= ~IOMAP_DIO_WRITE_THROUGH; 374 374 375 375 /* 376 376 * We can only do deferred completion for pure overwrites that
+2 -2
fs/kernfs/inode.c
··· 142 142 struct kernfs_node *kn = kernfs_dentry_node(dentry); 143 143 struct kernfs_iattrs *attrs; 144 144 145 - attrs = kernfs_iattrs_noalloc(kn); 145 + attrs = kernfs_iattrs(kn); 146 146 if (!attrs) 147 - return -ENODATA; 147 + return -ENOMEM; 148 148 149 149 return simple_xattr_list(d_inode(dentry), &attrs->xattrs, buf, size); 150 150 }
+22 -13
fs/namespace.c
··· 4551 4551 if (flags & MOVE_MOUNT_SET_GROUP) mflags |= MNT_TREE_PROPAGATION; 4552 4552 if (flags & MOVE_MOUNT_BENEATH) mflags |= MNT_TREE_BENEATH; 4553 4553 4554 - lflags = 0; 4555 - if (flags & MOVE_MOUNT_F_SYMLINKS) lflags |= LOOKUP_FOLLOW; 4556 - if (flags & MOVE_MOUNT_F_AUTOMOUNTS) lflags |= LOOKUP_AUTOMOUNT; 4557 4554 uflags = 0; 4558 - if (flags & MOVE_MOUNT_F_EMPTY_PATH) uflags = AT_EMPTY_PATH; 4559 - from_name = getname_maybe_null(from_pathname, uflags); 4560 - if (IS_ERR(from_name)) 4561 - return PTR_ERR(from_name); 4555 + if (flags & MOVE_MOUNT_T_EMPTY_PATH) 4556 + uflags = AT_EMPTY_PATH; 4562 4557 4563 - lflags = 0; 4564 - if (flags & MOVE_MOUNT_T_SYMLINKS) lflags |= LOOKUP_FOLLOW; 4565 - if (flags & MOVE_MOUNT_T_AUTOMOUNTS) lflags |= LOOKUP_AUTOMOUNT; 4566 - uflags = 0; 4567 - if (flags & MOVE_MOUNT_T_EMPTY_PATH) uflags = AT_EMPTY_PATH; 4568 4558 to_name = getname_maybe_null(to_pathname, uflags); 4569 4559 if (IS_ERR(to_name)) 4570 4560 return PTR_ERR(to_name); ··· 4567 4577 to_path = fd_file(f_to)->f_path; 4568 4578 path_get(&to_path); 4569 4579 } else { 4580 + lflags = 0; 4581 + if (flags & MOVE_MOUNT_T_SYMLINKS) 4582 + lflags |= LOOKUP_FOLLOW; 4583 + if (flags & MOVE_MOUNT_T_AUTOMOUNTS) 4584 + lflags |= LOOKUP_AUTOMOUNT; 4570 4585 ret = filename_lookup(to_dfd, to_name, lflags, &to_path, NULL); 4571 4586 if (ret) 4572 4587 return ret; 4573 4588 } 4589 + 4590 + uflags = 0; 4591 + if (flags & MOVE_MOUNT_F_EMPTY_PATH) 4592 + uflags = AT_EMPTY_PATH; 4593 + 4594 + from_name = getname_maybe_null(from_pathname, uflags); 4595 + if (IS_ERR(from_name)) 4596 + return PTR_ERR(from_name); 4574 4597 4575 4598 if (!from_name && from_dfd >= 0) { 4576 4599 CLASS(fd_raw, f_from)(from_dfd); ··· 4593 4590 return vfs_move_mount(&fd_file(f_from)->f_path, &to_path, mflags); 4594 4591 } 4595 4592 4593 + lflags = 0; 4594 + if (flags & MOVE_MOUNT_F_SYMLINKS) 4595 + lflags |= LOOKUP_FOLLOW; 4596 + if (flags & MOVE_MOUNT_F_AUTOMOUNTS) 4597 + lflags |= LOOKUP_AUTOMOUNT; 4596 4598 ret = filename_lookup(from_dfd, from_name, lflags, &from_path, NULL); 4597 4599 if (ret) 4598 4600 return ret; ··· 5184 5176 int ret; 5185 5177 struct mount_kattr kattr = {}; 5186 5178 5187 - kattr.kflags = MOUNT_KATTR_IDMAP_REPLACE; 5179 + if (flags & OPEN_TREE_CLONE) 5180 + kattr.kflags = MOUNT_KATTR_IDMAP_REPLACE; 5188 5181 if (flags & AT_RECURSIVE) 5189 5182 kattr.kflags |= MOUNT_KATTR_RECURSE; 5190 5183
+3 -1
fs/netfs/read_collect.c
··· 281 281 } else if (test_bit(NETFS_RREQ_SHORT_TRANSFER, &rreq->flags)) { 282 282 notes |= MADE_PROGRESS; 283 283 } else { 284 - if (!stream->failed) 284 + if (!stream->failed) { 285 285 stream->transferred += transferred; 286 + stream->transferred_valid = true; 287 + } 286 288 if (front->transferred < front->len) 287 289 set_bit(NETFS_RREQ_SHORT_TRANSFER, &rreq->flags); 288 290 notes |= MADE_PROGRESS;
+8 -2
fs/netfs/write_collect.c
··· 254 254 if (front->start + front->transferred > stream->collected_to) { 255 255 stream->collected_to = front->start + front->transferred; 256 256 stream->transferred = stream->collected_to - wreq->start; 257 + stream->transferred_valid = true; 257 258 notes |= MADE_PROGRESS; 258 259 } 259 260 if (test_bit(NETFS_SREQ_FAILED, &front->flags)) { ··· 357 356 { 358 357 struct netfs_inode *ictx = netfs_inode(wreq->inode); 359 358 size_t transferred; 359 + bool transferred_valid = false; 360 360 int s; 361 361 362 362 _enter("R=%x", wreq->debug_id); ··· 378 376 continue; 379 377 if (!list_empty(&stream->subrequests)) 380 378 return false; 381 - if (stream->transferred < transferred) 379 + if (stream->transferred_valid && 380 + stream->transferred < transferred) { 382 381 transferred = stream->transferred; 382 + transferred_valid = true; 383 + } 383 384 } 384 385 385 386 /* Okay, declare that all I/O is complete. */ 386 - wreq->transferred = transferred; 387 + if (transferred_valid) 388 + wreq->transferred = transferred; 387 389 trace_netfs_rreq(wreq, netfs_rreq_trace_write_done); 388 390 389 391 if (wreq->io_streams[1].active &&
+2 -2
fs/netfs/write_issue.c
··· 118 118 wreq->io_streams[0].prepare_write = ictx->ops->prepare_write; 119 119 wreq->io_streams[0].issue_write = ictx->ops->issue_write; 120 120 wreq->io_streams[0].collected_to = start; 121 - wreq->io_streams[0].transferred = LONG_MAX; 121 + wreq->io_streams[0].transferred = 0; 122 122 123 123 wreq->io_streams[1].stream_nr = 1; 124 124 wreq->io_streams[1].source = NETFS_WRITE_TO_CACHE; 125 125 wreq->io_streams[1].collected_to = start; 126 - wreq->io_streams[1].transferred = LONG_MAX; 126 + wreq->io_streams[1].transferred = 0; 127 127 if (fscache_resources_valid(&wreq->cache_resources)) { 128 128 wreq->io_streams[1].avail = true; 129 129 wreq->io_streams[1].active = true;
+1 -1
fs/pidfs.c
··· 296 296 static long pidfd_info(struct file *file, unsigned int cmd, unsigned long arg) 297 297 { 298 298 struct pidfd_info __user *uinfo = (struct pidfd_info __user *)arg; 299 + struct task_struct *task __free(put_task) = NULL; 299 300 struct pid *pid = pidfd_pid(file); 300 301 size_t usize = _IOC_SIZE(cmd); 301 302 struct pidfd_info kinfo = {}; 302 303 struct pidfs_exit_info *exit_info; 303 304 struct user_namespace *user_ns; 304 - struct task_struct *task; 305 305 struct pidfs_attr *attr; 306 306 const struct cred *c; 307 307 __u64 mask;
+3
fs/splice.c
··· 739 739 sd.pos = kiocb.ki_pos; 740 740 if (ret <= 0) 741 741 break; 742 + WARN_ONCE(ret > sd.total_len - left, 743 + "Splice Exceeded! ret=%zd tot=%zu left=%zu\n", 744 + ret, sd.total_len, left); 742 745 743 746 sd.num_spliced += ret; 744 747 sd.total_len -= ret;
+1 -1
include/linux/export.h
··· 91 91 #define EXPORT_SYMBOL_NS(sym, ns) __EXPORT_SYMBOL(sym, "", ns) 92 92 #define EXPORT_SYMBOL_NS_GPL(sym, ns) __EXPORT_SYMBOL(sym, "GPL", ns) 93 93 94 - #define EXPORT_SYMBOL_GPL_FOR_MODULES(sym, mods) __EXPORT_SYMBOL(sym, "GPL", "module:" mods) 94 + #define EXPORT_SYMBOL_FOR_MODULES(sym, mods) __EXPORT_SYMBOL(sym, "GPL", "module:" mods) 95 95 96 96 #endif /* _LINUX_EXPORT_H */
+1
include/linux/netfs.h
··· 150 150 bool active; /* T if stream is active */ 151 151 bool need_retry; /* T if this stream needs retrying */ 152 152 bool failed; /* T if this stream failed */ 153 + bool transferred_valid; /* T is ->transferred is valid */ 153 154 }; 154 155 155 156 /*
+5 -1
kernel/signal.c
··· 4067 4067 { 4068 4068 struct pid *pid; 4069 4069 enum pid_type type; 4070 + int ret; 4070 4071 4071 4072 /* Enforce flags be set to 0 until we add an extension. */ 4072 4073 if (flags & ~PIDFD_SEND_SIGNAL_FLAGS) ··· 4109 4108 } 4110 4109 } 4111 4110 4112 - return do_pidfd_send_signal(pid, sig, type, info, flags); 4111 + ret = do_pidfd_send_signal(pid, sig, type, info, flags); 4112 + put_pid(pid); 4113 + 4114 + return ret; 4113 4115 } 4114 4116 4115 4117 static int
-3
tools/testing/selftests/coredump/stackdump_test.c
··· 446 446 if (info.coredump_mask & PIDFD_COREDUMPED) 447 447 goto out; 448 448 449 - if (read(fd_coredump, &c, 1) < 1) 450 - goto out; 451 - 452 449 exit_code = EXIT_SUCCESS; 453 450 out: 454 451 if (fd_peer_pidfd >= 0)
+64 -13
tools/testing/selftests/mount_setattr/mount_setattr_test.c
··· 107 107 #endif 108 108 #endif 109 109 110 + #ifndef __NR_open_tree_attr 111 + #if defined __alpha__ 112 + #define __NR_open_tree_attr 577 113 + #elif defined _MIPS_SIM 114 + #if _MIPS_SIM == _MIPS_SIM_ABI32 /* o32 */ 115 + #define __NR_open_tree_attr (467 + 4000) 116 + #endif 117 + #if _MIPS_SIM == _MIPS_SIM_NABI32 /* n32 */ 118 + #define __NR_open_tree_attr (467 + 6000) 119 + #endif 120 + #if _MIPS_SIM == _MIPS_SIM_ABI64 /* n64 */ 121 + #define __NR_open_tree_attr (467 + 5000) 122 + #endif 123 + #elif defined __ia64__ 124 + #define __NR_open_tree_attr (467 + 1024) 125 + #else 126 + #define __NR_open_tree_attr 467 127 + #endif 128 + #endif 129 + 110 130 #ifndef MOUNT_ATTR_IDMAP 111 131 #define MOUNT_ATTR_IDMAP 0x00100000 112 132 #endif ··· 139 119 struct mount_attr *attr, size_t size) 140 120 { 141 121 return syscall(__NR_mount_setattr, dfd, path, flags, attr, size); 122 + } 123 + 124 + static inline int sys_open_tree_attr(int dfd, const char *path, unsigned int flags, 125 + struct mount_attr *attr, size_t size) 126 + { 127 + return syscall(__NR_open_tree_attr, dfd, path, flags, attr, size); 142 128 } 143 129 144 130 static ssize_t write_nointr(int fd, const void *buf, size_t count) ··· 1248 1222 attr.userns_fd = get_userns_fd(0, 10000, 10000); 1249 1223 ASSERT_GE(attr.userns_fd, 0); 1250 1224 ASSERT_NE(sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr)), 0); 1225 + /* 1226 + * Make sure that open_tree_attr() without OPEN_TREE_CLONE is not a way 1227 + * to bypass this mount_setattr() restriction. 1228 + */ 1229 + ASSERT_LT(sys_open_tree_attr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr)), 0); 1230 + 1251 1231 ASSERT_EQ(close(attr.userns_fd), 0); 1252 1232 ASSERT_EQ(close(open_tree_fd), 0); 1253 1233 } ··· 1287 1255 ASSERT_GE(attr.userns_fd, 0); 1288 1256 ASSERT_NE(sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, 1289 1257 sizeof(attr)), 0); 1258 + /* 1259 + * Make sure that open_tree_attr() without OPEN_TREE_CLONE is not a way 1260 + * to bypass this mount_setattr() restriction. 1261 + */ 1262 + ASSERT_LT(sys_open_tree_attr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr)), 0); 1263 + 1290 1264 ASSERT_EQ(close(attr.userns_fd), 0); 1291 1265 ASSERT_EQ(close(open_tree_fd), 0); 1292 1266 } ··· 1359 1321 ASSERT_EQ(close(open_tree_fd), 0); 1360 1322 } 1361 1323 1324 + static bool expected_uid_gid(int dfd, const char *path, int flags, 1325 + uid_t expected_uid, gid_t expected_gid) 1326 + { 1327 + int ret; 1328 + struct stat st; 1329 + 1330 + ret = fstatat(dfd, path, &st, flags); 1331 + if (ret < 0) 1332 + return false; 1333 + 1334 + return st.st_uid == expected_uid && st.st_gid == expected_gid; 1335 + } 1336 + 1362 1337 /** 1363 1338 * Validate that currently changing the idmapping of an idmapped mount fails. 1364 1339 */ ··· 1381 1330 struct mount_attr attr = { 1382 1331 .attr_set = MOUNT_ATTR_IDMAP, 1383 1332 }; 1333 + 1334 + ASSERT_TRUE(expected_uid_gid(-EBADF, "/mnt/D", 0, 0, 0)); 1384 1335 1385 1336 if (!mount_setattr_supported()) 1386 1337 SKIP(return, "mount_setattr syscall not supported"); ··· 1401 1348 AT_EMPTY_PATH, &attr, sizeof(attr)), 0); 1402 1349 ASSERT_EQ(close(attr.userns_fd), 0); 1403 1350 1351 + EXPECT_FALSE(expected_uid_gid(open_tree_fd, ".", 0, 0, 0)); 1352 + EXPECT_TRUE(expected_uid_gid(open_tree_fd, ".", 0, 10000, 10000)); 1353 + 1404 1354 /* Change idmapping on a detached mount that is already idmapped. */ 1405 1355 attr.userns_fd = get_userns_fd(0, 20000, 10000); 1406 1356 ASSERT_GE(attr.userns_fd, 0); 1407 1357 ASSERT_NE(sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr)), 0); 1358 + /* 1359 + * Make sure that open_tree_attr() without OPEN_TREE_CLONE is not a way 1360 + * to bypass this mount_setattr() restriction. 1361 + */ 1362 + EXPECT_LT(sys_open_tree_attr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr)), 0); 1363 + EXPECT_FALSE(expected_uid_gid(open_tree_fd, ".", 0, 20000, 20000)); 1364 + EXPECT_TRUE(expected_uid_gid(open_tree_fd, ".", 0, 10000, 10000)); 1365 + 1408 1366 ASSERT_EQ(close(attr.userns_fd), 0); 1409 1367 ASSERT_EQ(close(open_tree_fd), 0); 1410 - } 1411 - 1412 - static bool expected_uid_gid(int dfd, const char *path, int flags, 1413 - uid_t expected_uid, gid_t expected_gid) 1414 - { 1415 - int ret; 1416 - struct stat st; 1417 - 1418 - ret = fstatat(dfd, path, &st, flags); 1419 - if (ret < 0) 1420 - return false; 1421 - 1422 - return st.st_uid == expected_uid && st.st_gid == expected_gid; 1423 1368 } 1424 1369 1425 1370 TEST_F(mount_setattr_idmapped, idmap_mount_tree_invalid)