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.

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>

authored by

Benjamin Coddington and committed by
Chuck Lever
62346217 116b6b7a

+70 -3
+6
Documentation/netlink/specs/nfsd.yaml
··· 81 81 - 82 82 name: min-threads 83 83 type: u32 84 + - 85 + name: fh-key 86 + type: binary 87 + checks: 88 + exact-len: 16 84 89 - 85 90 name: version 86 91 attributes: ··· 168 163 - leasetime 169 164 - scope 170 165 - min-threads 166 + - fh-key 171 167 - 172 168 name: threads-get 173 169 doc: get the maximum number of running threads
+3 -2
fs/nfsd/netlink.c
··· 24 24 }; 25 25 26 26 /* NFSD_CMD_THREADS_SET - do */ 27 - static const struct nla_policy nfsd_threads_set_nl_policy[NFSD_A_SERVER_MIN_THREADS + 1] = { 27 + static const struct nla_policy nfsd_threads_set_nl_policy[NFSD_A_SERVER_FH_KEY + 1] = { 28 28 [NFSD_A_SERVER_THREADS] = { .type = NLA_U32, }, 29 29 [NFSD_A_SERVER_GRACETIME] = { .type = NLA_U32, }, 30 30 [NFSD_A_SERVER_LEASETIME] = { .type = NLA_U32, }, 31 31 [NFSD_A_SERVER_SCOPE] = { .type = NLA_NUL_STRING, }, 32 32 [NFSD_A_SERVER_MIN_THREADS] = { .type = NLA_U32, }, 33 + [NFSD_A_SERVER_FH_KEY] = NLA_POLICY_EXACT_LEN(16), 33 34 }; 34 35 35 36 /* NFSD_CMD_VERSION_SET - do */ ··· 59 58 .cmd = NFSD_CMD_THREADS_SET, 60 59 .doit = nfsd_nl_threads_set_doit, 61 60 .policy = nfsd_threads_set_nl_policy, 62 - .maxattr = NFSD_A_SERVER_MIN_THREADS, 61 + .maxattr = NFSD_A_SERVER_FH_KEY, 63 62 .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, 64 63 }, 65 64 {
+1
fs/nfsd/netns.h
··· 227 227 spinlock_t local_clients_lock; 228 228 struct list_head local_clients; 229 229 #endif 230 + siphash_key_t *fh_key; 230 231 }; 231 232 232 233 /* Simple check to find out if a given net was properly initialized */
+37 -1
fs/nfsd/nfsctl.c
··· 1582 1582 } 1583 1583 1584 1584 /** 1585 + * nfsd_nl_fh_key_set - helper to copy fh_key from userspace 1586 + * @attr: nlattr NFSD_A_SERVER_FH_KEY 1587 + * @nn: nfsd_net 1588 + * 1589 + * Callers should hold nfsd_mutex, returns 0 on success or negative errno. 1590 + * Callers must ensure the server is shut down (sv_nrthreads == 0), 1591 + * userspace documentation asserts the key may only be set when the server 1592 + * is not running. 1593 + */ 1594 + static int nfsd_nl_fh_key_set(const struct nlattr *attr, struct nfsd_net *nn) 1595 + { 1596 + siphash_key_t *fh_key = nn->fh_key; 1597 + 1598 + if (!fh_key) { 1599 + fh_key = kmalloc(sizeof(siphash_key_t), GFP_KERNEL); 1600 + if (!fh_key) 1601 + return -ENOMEM; 1602 + nn->fh_key = fh_key; 1603 + } 1604 + 1605 + fh_key->key[0] = get_unaligned_le64(nla_data(attr)); 1606 + fh_key->key[1] = get_unaligned_le64(nla_data(attr) + 8); 1607 + return 0; 1608 + } 1609 + 1610 + /** 1585 1611 * nfsd_nl_threads_set_doit - set the number of running threads 1586 1612 * @skb: reply buffer 1587 1613 * @info: netlink metadata and command arguments ··· 1648 1622 1649 1623 if (info->attrs[NFSD_A_SERVER_GRACETIME] || 1650 1624 info->attrs[NFSD_A_SERVER_LEASETIME] || 1651 - info->attrs[NFSD_A_SERVER_SCOPE]) { 1625 + info->attrs[NFSD_A_SERVER_SCOPE] || 1626 + info->attrs[NFSD_A_SERVER_FH_KEY]) { 1652 1627 ret = -EBUSY; 1653 1628 if (nn->nfsd_serv && nn->nfsd_serv->sv_nrthreads) 1654 1629 goto out_unlock; ··· 1678 1651 attr = info->attrs[NFSD_A_SERVER_SCOPE]; 1679 1652 if (attr) 1680 1653 scope = nla_data(attr); 1654 + 1655 + attr = info->attrs[NFSD_A_SERVER_FH_KEY]; 1656 + if (attr) { 1657 + ret = nfsd_nl_fh_key_set(attr, nn); 1658 + trace_nfsd_ctl_fh_key_set((const char *)nn->fh_key, ret); 1659 + if (ret) 1660 + goto out_unlock; 1661 + } 1681 1662 } 1682 1663 1683 1664 attr = info->attrs[NFSD_A_SERVER_MIN_THREADS]; ··· 2272 2237 { 2273 2238 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 2274 2239 2240 + kfree_sensitive(nn->fh_key); 2275 2241 nfsd_proc_stat_shutdown(net); 2276 2242 percpu_counter_destroy_many(nn->counter, NFSD_STATS_COUNTERS_NUM); 2277 2243 nfsd_idmap_shutdown(net);
+22
fs/nfsd/trace.h
··· 2240 2240 ) 2241 2241 ); 2242 2242 2243 + TRACE_EVENT(nfsd_ctl_fh_key_set, 2244 + TP_PROTO( 2245 + const char *key, 2246 + int result 2247 + ), 2248 + TP_ARGS(key, result), 2249 + TP_STRUCT__entry( 2250 + __field(u32, key_hash) 2251 + __field(int, result) 2252 + ), 2253 + TP_fast_assign( 2254 + if (key) 2255 + __entry->key_hash = ~crc32_le(0xFFFFFFFF, key, 16); 2256 + else 2257 + __entry->key_hash = 0; 2258 + __entry->result = result; 2259 + ), 2260 + TP_printk("key=0x%08x result=%d", 2261 + __entry->key_hash, __entry->result 2262 + ) 2263 + ); 2264 + 2243 2265 DECLARE_EVENT_CLASS(nfsd_copy_class, 2244 2266 TP_PROTO( 2245 2267 const struct nfsd4_copy *copy
+1
include/uapi/linux/nfsd_netlink.h
··· 36 36 NFSD_A_SERVER_LEASETIME, 37 37 NFSD_A_SERVER_SCOPE, 38 38 NFSD_A_SERVER_MIN_THREADS, 39 + NFSD_A_SERVER_FH_KEY, 39 40 40 41 __NFSD_A_SERVER_MAX, 41 42 NFSD_A_SERVER_MAX = (__NFSD_A_SERVER_MAX - 1)