Skip to content

cred: properly pass and test creds on other threads #17273

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion include/os/freebsd/spl/sys/policy.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ struct znode;

int secpolicy_nfs(cred_t *cr);
int secpolicy_zfs(cred_t *crd);
int secpolicy_zfs_proc(cred_t *cr, proc_t *proc);
int secpolicy_sys_config(cred_t *cr, int checkonly);
int secpolicy_zinject(cred_t *cr);
int secpolicy_fs_unmount(cred_t *cr, struct mount *vfsp);
Expand Down
1 change: 0 additions & 1 deletion include/os/linux/zfs/sys/policy.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ int secpolicy_vnode_setids_setgids(const cred_t *, gid_t, zidmap_t *,
struct user_namespace *);
int secpolicy_zinject(const cred_t *);
int secpolicy_zfs(const cred_t *);
int secpolicy_zfs_proc(const cred_t *, proc_t *);
void secpolicy_setid_clear(vattr_t *, cred_t *);
int secpolicy_setid_setsticky_clear(struct inode *, vattr_t *,
const vattr_t *, cred_t *, zidmap_t *, struct user_namespace *);
Expand Down
1 change: 0 additions & 1 deletion include/sys/dmu_recv.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ typedef struct dmu_recv_cookie {
uint64_t drc_ivset_guid;
void *drc_owner;
cred_t *drc_cred;
proc_t *drc_proc;
nvlist_t *drc_begin_nvl;

objset_t *drc_os;
Expand Down
4 changes: 1 addition & 3 deletions include/sys/dsl_dataset.h
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,6 @@ typedef struct dsl_dataset_promote_arg {
uint64_t used, comp, uncomp, unique, cloneusedsnap, originusedsnap;
nvlist_t *err_ds;
cred_t *cr;
proc_t *proc;
} dsl_dataset_promote_arg_t;

typedef struct dsl_dataset_rollback_arg {
Expand All @@ -299,7 +298,6 @@ typedef struct dsl_dataset_snapshot_arg {
nvlist_t *ddsa_props;
nvlist_t *ddsa_errors;
cred_t *ddsa_cr;
proc_t *ddsa_proc;
} dsl_dataset_snapshot_arg_t;

typedef struct dsl_dataset_rename_snapshot_arg {
Expand Down Expand Up @@ -459,7 +457,7 @@ int dsl_dataset_clone_swap_check_impl(dsl_dataset_t *clone,
void dsl_dataset_clone_swap_sync_impl(dsl_dataset_t *clone,
dsl_dataset_t *origin_head, dmu_tx_t *tx);
int dsl_dataset_snapshot_check_impl(dsl_dataset_t *ds, const char *snapname,
dmu_tx_t *tx, boolean_t recv, uint64_t cnt, cred_t *cr, proc_t *proc);
dmu_tx_t *tx, boolean_t recv, uint64_t cnt, cred_t *cr);
void dsl_dataset_snapshot_sync_impl(dsl_dataset_t *ds, const char *snapname,
dmu_tx_t *tx);

Expand Down
4 changes: 2 additions & 2 deletions include/sys/dsl_dir.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,11 +185,11 @@ int dsl_dir_set_reservation(const char *ddname, zprop_source_t source,
uint64_t reservation);
int dsl_dir_activate_fs_ss_limit(const char *);
int dsl_fs_ss_limit_check(dsl_dir_t *, uint64_t, zfs_prop_t, dsl_dir_t *,
cred_t *, proc_t *);
cred_t *);
void dsl_fs_ss_count_adjust(dsl_dir_t *, int64_t, const char *, dmu_tx_t *);
int dsl_dir_rename(const char *oldname, const char *newname);
int dsl_dir_transfer_possible(dsl_dir_t *sdd, dsl_dir_t *tdd,
uint64_t fs_cnt, uint64_t ss_cnt, uint64_t space, cred_t *, proc_t *);
uint64_t fs_cnt, uint64_t ss_cnt, uint64_t space, cred_t *);
boolean_t dsl_dir_is_clone(dsl_dir_t *dd);
void dsl_dir_new_refreservation(dsl_dir_t *dd, struct dsl_dataset *ds,
uint64_t reservation, cred_t *cr, dmu_tx_t *tx);
Expand Down
1 change: 0 additions & 1 deletion include/sys/zcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ typedef struct zcp_run_info {
* rather than the 'current' thread's.
*/
cred_t *zri_cred;
proc_t *zri_proc;

/*
* The tx in which this channel program is running.
Expand Down
4 changes: 3 additions & 1 deletion include/sys/zfs_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,9 @@ extern void delay(clock_t ticks);
#define kcred NULL
#define CRED() NULL

#define crhold(cr) ((void)cr)
#define crfree(cr) ((void)cr)

#define ptob(x) ((x) * PAGESIZE)

#define NN_DIVISOR_1000 (1U << 0)
Expand Down Expand Up @@ -744,7 +747,6 @@ extern int zfs_secpolicy_rename_perms(const char *from, const char *to,
cred_t *cr);
extern int zfs_secpolicy_destroy_perms(const char *name, cred_t *cr);
extern int secpolicy_zfs(const cred_t *cr);
extern int secpolicy_zfs_proc(const cred_t *cr, proc_t *proc);
extern zoneid_t getzoneid(void);

/* SID stuff */
Expand Down
7 changes: 0 additions & 7 deletions lib/libzpool/kernel.c
Original file line number Diff line number Diff line change
Expand Up @@ -918,13 +918,6 @@ secpolicy_zfs(const cred_t *cr)
return (0);
}

int
secpolicy_zfs_proc(const cred_t *cr, proc_t *proc)
{
(void) cr, (void) proc;
return (0);
}

ksiddomain_t *
ksid_lookupdomain(const char *dom)
{
Expand Down
7 changes: 0 additions & 7 deletions module/os/freebsd/spl/spl_policy.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,6 @@ secpolicy_zfs(cred_t *cr)
return (priv_check_cred(cr, PRIV_VFS_MOUNT));
}

int
secpolicy_zfs_proc(cred_t *cr, proc_t *proc)
{

return (priv_check_cred(cr, PRIV_VFS_MOUNT));
}

int
secpolicy_sys_config(cred_t *cr, int checkonly __unused)
{
Expand Down
44 changes: 18 additions & 26 deletions module/os/linux/zfs/policy.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2013, Joyent, Inc. All rights reserved.
* Copyright (C) 2016 Lawrence Livermore National Security, LLC.
* Copyright (c) 2025, Rob Norris <[email protected]>
*
* For Linux the vast majority of this enforcement is already handled via
* the standard Linux VFS permission checks. However certain administrative
Expand All @@ -35,28 +36,32 @@
#include <linux/security.h>
#include <linux/vfs_compat.h>

/*
* The passed credentials cannot be directly verified because Linux only
* provides and interface to check the *current* process credentials. In
* order to handle this the capable() test is only run when the passed
* credentials match the current process credentials or the kcred. In
* all other cases this function must fail and return the passed err.
*/
static int
priv_policy_ns(const cred_t *cr, int capability, int err,
struct user_namespace *ns)
{
if (cr != CRED() && (cr != kcred))
return (err);
/*
* The passed credentials cannot be directly verified because Linux
* only provides an interface to check the *current* process
* credentials. In order to handle this we check if the passed in
* creds match the current process credentials or the kcred. If not,
* we swap the passed credentials into the current task, perform the
* check, and then revert it before returning.
*/
const cred_t *old =
(cr != CRED() && cr != kcred) ? override_creds(cr) : NULL;

#if defined(CONFIG_USER_NS)
if (!(ns ? ns_capable(ns, capability) : capable(capability)))
if (ns ? ns_capable(ns, capability) : capable(capability))
#else
if (!capable(capability))
if (capable(capability))
#endif
return (err);
err = 0;

return (0);
if (old)
revert_creds(old);

return (err);
}

static int
Expand Down Expand Up @@ -249,19 +254,6 @@ secpolicy_zfs(const cred_t *cr)
return (priv_policy(cr, CAP_SYS_ADMIN, EACCES));
}

/*
* Equivalent to secpolicy_zfs(), but works even if the cred_t is not that of
* the current process. Takes both cred_t and proc_t so that this can work
* easily on all platforms.
*/
int
secpolicy_zfs_proc(const cred_t *cr, proc_t *proc)
{
if (!has_capability(proc, CAP_SYS_ADMIN))
return (EACCES);
return (0);
}

void
secpolicy_setid_clear(vattr_t *vap, cred_t *cr)
{
Expand Down
25 changes: 17 additions & 8 deletions module/zfs/dmu_objset.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
* Copyright (c) 2019, Klara Inc.
* Copyright (c) 2019, Allan Jude
* Copyright (c) 2022 Hewlett Packard Enterprise Development LP.
* Copyright (c) 2025, Rob Norris <[email protected]>
*/

/* Portions Copyright 2010 Robert Milkowski */
Expand Down Expand Up @@ -68,6 +69,7 @@
#include <sys/vdev_impl.h>
#include <sys/arc.h>
#include <cityhash.h>
#include <sys/cred.h>

/*
* Needed to close a window in dnode_move() that allows the objset to be freed
Expand Down Expand Up @@ -1179,7 +1181,6 @@ dmu_objset_create_impl(spa_t *spa, dsl_dataset_t *ds, blkptr_t *bp,
typedef struct dmu_objset_create_arg {
const char *doca_name;
cred_t *doca_cred;
proc_t *doca_proc;
void (*doca_userfunc)(objset_t *os, void *arg,
cred_t *cr, dmu_tx_t *tx);
void *doca_userarg;
Expand Down Expand Up @@ -1223,7 +1224,7 @@ dmu_objset_create_check(void *arg, dmu_tx_t *tx)
}

error = dsl_fs_ss_limit_check(pdd, 1, ZFS_PROP_FILESYSTEM_LIMIT, NULL,
doca->doca_cred, doca->doca_proc);
doca->doca_cred);
if (error != 0) {
dsl_dir_rele(pdd, FTAG);
return (error);
Expand Down Expand Up @@ -1350,9 +1351,11 @@ dmu_objset_create(const char *name, dmu_objset_type_t type, uint64_t flags,
dmu_objset_create_arg_t doca;
dsl_crypto_params_t tmp_dcp = { 0 };

cred_t *cr = CRED();
crhold(cr);

doca.doca_name = name;
doca.doca_cred = CRED();
doca.doca_proc = curproc;
doca.doca_cred = cr;
doca.doca_flags = flags;
doca.doca_userfunc = func;
doca.doca_userarg = arg;
Expand All @@ -1374,14 +1377,16 @@ dmu_objset_create(const char *name, dmu_objset_type_t type, uint64_t flags,

if (rv == 0)
zvol_create_minor(name);

crfree(cr);

return (rv);
}

typedef struct dmu_objset_clone_arg {
const char *doca_clone;
const char *doca_origin;
cred_t *doca_cred;
proc_t *doca_proc;
} dmu_objset_clone_arg_t;

static int
Expand Down Expand Up @@ -1409,7 +1414,7 @@ dmu_objset_clone_check(void *arg, dmu_tx_t *tx)
}

error = dsl_fs_ss_limit_check(pdd, 1, ZFS_PROP_FILESYSTEM_LIMIT, NULL,
doca->doca_cred, doca->doca_proc);
doca->doca_cred);
if (error != 0) {
dsl_dir_rele(pdd, FTAG);
return (SET_ERROR(EDQUOT));
Expand Down Expand Up @@ -1465,10 +1470,12 @@ dmu_objset_clone(const char *clone, const char *origin)
{
dmu_objset_clone_arg_t doca;

cred_t *cr = CRED();
crhold(cr);

doca.doca_clone = clone;
doca.doca_origin = origin;
doca.doca_cred = CRED();
doca.doca_proc = curproc;
doca.doca_cred = cr;

int rv = dsl_sync_task(clone,
dmu_objset_clone_check, dmu_objset_clone_sync, &doca,
Expand All @@ -1477,6 +1484,8 @@ dmu_objset_clone(const char *clone, const char *origin)
if (rv == 0)
zvol_create_minor(clone);

crfree(cr);

return (rv);
}

Expand Down
Loading