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

ovl: refactor ovl_fill_super()

Split the core into a separate helper in preparation of converting the
caller to the scoped ovl cred guard.

Link: https://patch.msgid.link/20251117-work-ovl-cred-guard-v4-40-b31603935724@kernel.org
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Christian Brauner <brauner@kernel.org>

+50 -45
+50 -45
fs/overlayfs/super.c
··· 1364 1364 set_default_d_op(sb, &ovl_dentry_operations); 1365 1365 } 1366 1366 1367 - int ovl_fill_super(struct super_block *sb, struct fs_context *fc) 1367 + static int ovl_fill_super_creds(struct fs_context *fc, struct super_block *sb) 1368 1368 { 1369 1369 struct ovl_fs *ofs = sb->s_fs_info; 1370 + struct cred *creator_cred = (struct cred *)ofs->creator_cred; 1370 1371 struct ovl_fs_context *ctx = fc->fs_private; 1371 - const struct cred *old_cred = NULL; 1372 - struct dentry *root_dentry; 1373 - struct ovl_entry *oe; 1374 1372 struct ovl_layer *layers; 1375 - struct cred *cred; 1373 + struct ovl_entry *oe = NULL; 1376 1374 int err; 1377 - 1378 - err = -EIO; 1379 - if (WARN_ON(fc->user_ns != current_user_ns())) 1380 - goto out_err; 1381 - 1382 - ovl_set_d_op(sb); 1383 - 1384 - err = -ENOMEM; 1385 - if (!ofs->creator_cred) 1386 - ofs->creator_cred = cred = prepare_creds(); 1387 - else 1388 - cred = (struct cred *)ofs->creator_cred; 1389 - if (!cred) 1390 - goto out_err; 1391 - 1392 - old_cred = ovl_override_creds(sb); 1393 1375 1394 1376 err = ovl_fs_params_verify(ctx, &ofs->config); 1395 1377 if (err) 1396 - goto out_err; 1378 + return err; 1397 1379 1398 1380 err = -EINVAL; 1399 1381 if (ctx->nr == 0) { 1400 1382 if (!(fc->sb_flags & SB_SILENT)) 1401 1383 pr_err("missing 'lowerdir'\n"); 1402 - goto out_err; 1384 + return err; 1403 1385 } 1404 1386 1405 1387 err = -ENOMEM; 1406 1388 layers = kcalloc(ctx->nr + 1, sizeof(struct ovl_layer), GFP_KERNEL); 1407 1389 if (!layers) 1408 - goto out_err; 1390 + return err; 1409 1391 1410 1392 ofs->config.lowerdirs = kcalloc(ctx->nr + 1, sizeof(char *), GFP_KERNEL); 1411 1393 if (!ofs->config.lowerdirs) { 1412 1394 kfree(layers); 1413 - goto out_err; 1395 + return err; 1414 1396 } 1415 1397 ofs->layers = layers; 1416 1398 /* ··· 1425 1443 err = -EINVAL; 1426 1444 if (!ofs->config.workdir) { 1427 1445 pr_err("missing 'workdir'\n"); 1428 - goto out_err; 1446 + return err; 1429 1447 } 1430 1448 1431 1449 err = ovl_get_upper(sb, ofs, &layers[0], &ctx->upper); 1432 1450 if (err) 1433 - goto out_err; 1451 + return err; 1434 1452 1435 1453 upper_sb = ovl_upper_mnt(ofs)->mnt_sb; 1436 1454 if (!ovl_should_sync(ofs)) { ··· 1438 1456 if (errseq_check(&upper_sb->s_wb_err, ofs->errseq)) { 1439 1457 err = -EIO; 1440 1458 pr_err("Cannot mount volatile when upperdir has an unseen error. Sync upperdir fs to clear state.\n"); 1441 - goto out_err; 1459 + return err; 1442 1460 } 1443 1461 } 1444 1462 1445 1463 err = ovl_get_workdir(sb, ofs, &ctx->upper, &ctx->work); 1446 1464 if (err) 1447 - goto out_err; 1465 + return err; 1448 1466 1449 1467 if (!ofs->workdir) 1450 1468 sb->s_flags |= SB_RDONLY; ··· 1455 1473 oe = ovl_get_lowerstack(sb, ctx, ofs, layers); 1456 1474 err = PTR_ERR(oe); 1457 1475 if (IS_ERR(oe)) 1458 - goto out_err; 1476 + return err; 1459 1477 1460 1478 /* If the upper fs is nonexistent, we mark overlayfs r/o too */ 1461 1479 if (!ovl_upper_mnt(ofs)) ··· 1508 1526 sb->s_export_op = &ovl_export_fid_operations; 1509 1527 1510 1528 /* Never override disk quota limits or use reserved space */ 1511 - cap_lower(cred->cap_effective, CAP_SYS_RESOURCE); 1529 + cap_lower(creator_cred->cap_effective, CAP_SYS_RESOURCE); 1512 1530 1513 1531 sb->s_magic = OVERLAYFS_SUPER_MAGIC; 1514 1532 sb->s_xattr = ovl_xattr_handlers(ofs); ··· 1526 1544 sb->s_iflags |= SB_I_EVM_HMAC_UNSUPPORTED; 1527 1545 1528 1546 err = -ENOMEM; 1529 - root_dentry = ovl_get_root(sb, ctx->upper.dentry, oe); 1530 - if (!root_dentry) 1547 + sb->s_root = ovl_get_root(sb, ctx->upper.dentry, oe); 1548 + if (!sb->s_root) 1531 1549 goto out_free_oe; 1532 1550 1533 - sb->s_root = root_dentry; 1534 - 1535 - ovl_revert_creds(old_cred); 1536 1551 return 0; 1537 1552 1538 1553 out_free_oe: 1539 1554 ovl_free_entry(oe); 1555 + return err; 1556 + } 1557 + 1558 + int ovl_fill_super(struct super_block *sb, struct fs_context *fc) 1559 + { 1560 + struct ovl_fs *ofs = sb->s_fs_info; 1561 + const struct cred *old_cred = NULL; 1562 + struct cred *cred; 1563 + int err; 1564 + 1565 + err = -EIO; 1566 + if (WARN_ON(fc->user_ns != current_user_ns())) 1567 + goto out_err; 1568 + 1569 + ovl_set_d_op(sb); 1570 + 1571 + err = -ENOMEM; 1572 + if (!ofs->creator_cred) 1573 + ofs->creator_cred = cred = prepare_creds(); 1574 + else 1575 + cred = (struct cred *)ofs->creator_cred; 1576 + if (!cred) 1577 + goto out_err; 1578 + 1579 + old_cred = ovl_override_creds(sb); 1580 + 1581 + err = ovl_fill_super_creds(fc, sb); 1582 + 1583 + ovl_revert_creds(old_cred); 1584 + 1540 1585 out_err: 1541 - /* 1542 - * Revert creds before calling ovl_free_fs() which will call 1543 - * put_cred() and put_cred() requires that the cred's that are 1544 - * put are not the caller's creds, i.e., current->cred. 1545 - */ 1546 - if (old_cred) 1547 - ovl_revert_creds(old_cred); 1548 - ovl_free_fs(ofs); 1549 - sb->s_fs_info = NULL; 1586 + if (err) { 1587 + ovl_free_fs(ofs); 1588 + sb->s_fs_info = NULL; 1589 + } 1590 + 1550 1591 return err; 1551 1592 } 1552 1593