mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 18:13:41 +02:00
NFSD: Add a key for signing filehandles
A future patch will enable NFSD to sign filehandles by appending a Message Authentication Code(MAC). To do this, NFSD requires a secret 128-bit key that can persist across reboots. A persisted key allows the server to accept filehandles after a restart. Enable NFSD to be configured with this key via the netlink interface. Link: https://lore.kernel.org/linux-nfs/cover.1772022373.git.bcodding@hammerspace.com Signed-off-by: Benjamin Coddington <bcodding@hammerspace.com> Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
This commit is contained in:
parent
116b6b7acd
commit
62346217fd
|
|
@ -81,6 +81,11 @@ attribute-sets:
|
|||
-
|
||||
name: min-threads
|
||||
type: u32
|
||||
-
|
||||
name: fh-key
|
||||
type: binary
|
||||
checks:
|
||||
exact-len: 16
|
||||
-
|
||||
name: version
|
||||
attributes:
|
||||
|
|
@ -163,6 +168,7 @@ operations:
|
|||
- leasetime
|
||||
- scope
|
||||
- min-threads
|
||||
- fh-key
|
||||
-
|
||||
name: threads-get
|
||||
doc: get the maximum number of running threads
|
||||
|
|
|
|||
|
|
@ -24,12 +24,13 @@ const struct nla_policy nfsd_version_nl_policy[NFSD_A_VERSION_ENABLED + 1] = {
|
|||
};
|
||||
|
||||
/* NFSD_CMD_THREADS_SET - do */
|
||||
static const struct nla_policy nfsd_threads_set_nl_policy[NFSD_A_SERVER_MIN_THREADS + 1] = {
|
||||
static const struct nla_policy nfsd_threads_set_nl_policy[NFSD_A_SERVER_FH_KEY + 1] = {
|
||||
[NFSD_A_SERVER_THREADS] = { .type = NLA_U32, },
|
||||
[NFSD_A_SERVER_GRACETIME] = { .type = NLA_U32, },
|
||||
[NFSD_A_SERVER_LEASETIME] = { .type = NLA_U32, },
|
||||
[NFSD_A_SERVER_SCOPE] = { .type = NLA_NUL_STRING, },
|
||||
[NFSD_A_SERVER_MIN_THREADS] = { .type = NLA_U32, },
|
||||
[NFSD_A_SERVER_FH_KEY] = NLA_POLICY_EXACT_LEN(16),
|
||||
};
|
||||
|
||||
/* NFSD_CMD_VERSION_SET - do */
|
||||
|
|
@ -58,7 +59,7 @@ static const struct genl_split_ops nfsd_nl_ops[] = {
|
|||
.cmd = NFSD_CMD_THREADS_SET,
|
||||
.doit = nfsd_nl_threads_set_doit,
|
||||
.policy = nfsd_threads_set_nl_policy,
|
||||
.maxattr = NFSD_A_SERVER_MIN_THREADS,
|
||||
.maxattr = NFSD_A_SERVER_FH_KEY,
|
||||
.flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -227,6 +227,7 @@ struct nfsd_net {
|
|||
spinlock_t local_clients_lock;
|
||||
struct list_head local_clients;
|
||||
#endif
|
||||
siphash_key_t *fh_key;
|
||||
};
|
||||
|
||||
/* Simple check to find out if a given net was properly initialized */
|
||||
|
|
|
|||
|
|
@ -1581,6 +1581,32 @@ int nfsd_nl_rpc_status_get_dumpit(struct sk_buff *skb,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* nfsd_nl_fh_key_set - helper to copy fh_key from userspace
|
||||
* @attr: nlattr NFSD_A_SERVER_FH_KEY
|
||||
* @nn: nfsd_net
|
||||
*
|
||||
* Callers should hold nfsd_mutex, returns 0 on success or negative errno.
|
||||
* Callers must ensure the server is shut down (sv_nrthreads == 0),
|
||||
* userspace documentation asserts the key may only be set when the server
|
||||
* is not running.
|
||||
*/
|
||||
static int nfsd_nl_fh_key_set(const struct nlattr *attr, struct nfsd_net *nn)
|
||||
{
|
||||
siphash_key_t *fh_key = nn->fh_key;
|
||||
|
||||
if (!fh_key) {
|
||||
fh_key = kmalloc(sizeof(siphash_key_t), GFP_KERNEL);
|
||||
if (!fh_key)
|
||||
return -ENOMEM;
|
||||
nn->fh_key = fh_key;
|
||||
}
|
||||
|
||||
fh_key->key[0] = get_unaligned_le64(nla_data(attr));
|
||||
fh_key->key[1] = get_unaligned_le64(nla_data(attr) + 8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* nfsd_nl_threads_set_doit - set the number of running threads
|
||||
* @skb: reply buffer
|
||||
|
|
@ -1622,7 +1648,8 @@ int nfsd_nl_threads_set_doit(struct sk_buff *skb, struct genl_info *info)
|
|||
|
||||
if (info->attrs[NFSD_A_SERVER_GRACETIME] ||
|
||||
info->attrs[NFSD_A_SERVER_LEASETIME] ||
|
||||
info->attrs[NFSD_A_SERVER_SCOPE]) {
|
||||
info->attrs[NFSD_A_SERVER_SCOPE] ||
|
||||
info->attrs[NFSD_A_SERVER_FH_KEY]) {
|
||||
ret = -EBUSY;
|
||||
if (nn->nfsd_serv && nn->nfsd_serv->sv_nrthreads)
|
||||
goto out_unlock;
|
||||
|
|
@ -1651,6 +1678,14 @@ int nfsd_nl_threads_set_doit(struct sk_buff *skb, struct genl_info *info)
|
|||
attr = info->attrs[NFSD_A_SERVER_SCOPE];
|
||||
if (attr)
|
||||
scope = nla_data(attr);
|
||||
|
||||
attr = info->attrs[NFSD_A_SERVER_FH_KEY];
|
||||
if (attr) {
|
||||
ret = nfsd_nl_fh_key_set(attr, nn);
|
||||
trace_nfsd_ctl_fh_key_set((const char *)nn->fh_key, ret);
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
}
|
||||
}
|
||||
|
||||
attr = info->attrs[NFSD_A_SERVER_MIN_THREADS];
|
||||
|
|
@ -2237,6 +2272,7 @@ static __net_exit void nfsd_net_exit(struct net *net)
|
|||
{
|
||||
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
||||
|
||||
kfree_sensitive(nn->fh_key);
|
||||
nfsd_proc_stat_shutdown(net);
|
||||
percpu_counter_destroy_many(nn->counter, NFSD_STATS_COUNTERS_NUM);
|
||||
nfsd_idmap_shutdown(net);
|
||||
|
|
|
|||
|
|
@ -2240,6 +2240,28 @@ TRACE_EVENT(nfsd_end_grace,
|
|||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(nfsd_ctl_fh_key_set,
|
||||
TP_PROTO(
|
||||
const char *key,
|
||||
int result
|
||||
),
|
||||
TP_ARGS(key, result),
|
||||
TP_STRUCT__entry(
|
||||
__field(u32, key_hash)
|
||||
__field(int, result)
|
||||
),
|
||||
TP_fast_assign(
|
||||
if (key)
|
||||
__entry->key_hash = ~crc32_le(0xFFFFFFFF, key, 16);
|
||||
else
|
||||
__entry->key_hash = 0;
|
||||
__entry->result = result;
|
||||
),
|
||||
TP_printk("key=0x%08x result=%d",
|
||||
__entry->key_hash, __entry->result
|
||||
)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(nfsd_copy_class,
|
||||
TP_PROTO(
|
||||
const struct nfsd4_copy *copy
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ enum {
|
|||
NFSD_A_SERVER_LEASETIME,
|
||||
NFSD_A_SERVER_SCOPE,
|
||||
NFSD_A_SERVER_MIN_THREADS,
|
||||
NFSD_A_SERVER_FH_KEY,
|
||||
|
||||
__NFSD_A_SERVER_MAX,
|
||||
NFSD_A_SERVER_MAX = (__NFSD_A_SERVER_MAX - 1)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user