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.18-rc8.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs

Pull vfs fixes from Christian Brauner:

- afs: Fix delayed allocation of a cell's anonymous key

The allocation of a cell's anonymous key is done in a background
thread along with other cell setup such as doing a DNS upcall. The
normal key lookup tries to use the key description on the anonymous
authentication key as the reference for request_key() - but it may
not yet be set, causing an oops

- ovl: fail ovl_lock_rename_workdir() if either target is unhashed

As well as checking that the parent hasn't changed after getting the
lock, the code needs to check that the dentry hasn't been unhashed.
Otherwise overlayfs might try to rename something that has been
removed

- namespace: fix a reference leak in grab_requested_mnt_ns

lookup_mnt_ns() already takes a reference on mnt_ns, and so
grab_requested_mnt_ns() doesn't need to take an extra reference

* tag 'vfs-6.18-rc8.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs:
afs: Fix delayed allocation of a cell's anonymous key
ovl: fail ovl_lock_rename_workdir() if either target is unhashed
fs/namespace: fix reference leak in grab_requested_mnt_ns

+55 -48
+8 -35
fs/afs/cell.c
··· 140 140 return ERR_PTR(-ENOMEM); 141 141 } 142 142 143 - cell->name = kmalloc(1 + namelen + 1, GFP_KERNEL); 143 + /* Allocate the cell name and the key name in one go. */ 144 + cell->name = kmalloc(1 + namelen + 1 + 145 + 4 + namelen + 1, GFP_KERNEL); 144 146 if (!cell->name) { 145 147 kfree(cell); 146 148 return ERR_PTR(-ENOMEM); ··· 153 151 cell->name_len = namelen; 154 152 for (i = 0; i < namelen; i++) 155 153 cell->name[i] = tolower(name[i]); 156 - cell->name[i] = 0; 154 + cell->name[i++] = 0; 155 + 156 + cell->key_desc = cell->name + i; 157 + memcpy(cell->key_desc, "afs@", 4); 158 + memcpy(cell->key_desc + 4, cell->name, cell->name_len + 1); 157 159 158 160 cell->net = net; 159 161 refcount_set(&cell->ref, 1); ··· 717 711 } 718 712 719 713 /* 720 - * Allocate a key to use as a placeholder for anonymous user security. 721 - */ 722 - static int afs_alloc_anon_key(struct afs_cell *cell) 723 - { 724 - struct key *key; 725 - char keyname[4 + AFS_MAXCELLNAME + 1], *cp, *dp; 726 - 727 - /* Create a key to represent an anonymous user. */ 728 - memcpy(keyname, "afs@", 4); 729 - dp = keyname + 4; 730 - cp = cell->name; 731 - do { 732 - *dp++ = tolower(*cp); 733 - } while (*cp++); 734 - 735 - key = rxrpc_get_null_key(keyname); 736 - if (IS_ERR(key)) 737 - return PTR_ERR(key); 738 - 739 - cell->anonymous_key = key; 740 - 741 - _debug("anon key %p{%x}", 742 - cell->anonymous_key, key_serial(cell->anonymous_key)); 743 - return 0; 744 - } 745 - 746 - /* 747 714 * Activate a cell. 748 715 */ 749 716 static int afs_activate_cell(struct afs_net *net, struct afs_cell *cell) ··· 724 745 struct hlist_node **p; 725 746 struct afs_cell *pcell; 726 747 int ret; 727 - 728 - if (!cell->anonymous_key) { 729 - ret = afs_alloc_anon_key(cell); 730 - if (ret < 0) 731 - return ret; 732 - } 733 748 734 749 ret = afs_proc_cell_setup(cell); 735 750 if (ret < 0)
+1
fs/afs/internal.h
··· 413 413 414 414 u8 name_len; /* Length of name */ 415 415 char *name; /* Cell name, case-flattened and NUL-padded */ 416 + char *key_desc; /* Authentication key description */ 416 417 }; 417 418 418 419 /*
+40 -8
fs/afs/security.c
··· 16 16 17 17 static DEFINE_HASHTABLE(afs_permits_cache, 10); 18 18 static DEFINE_SPINLOCK(afs_permits_lock); 19 + static DEFINE_MUTEX(afs_key_lock); 20 + 21 + /* 22 + * Allocate a key to use as a placeholder for anonymous user security. 23 + */ 24 + static int afs_alloc_anon_key(struct afs_cell *cell) 25 + { 26 + struct key *key; 27 + 28 + mutex_lock(&afs_key_lock); 29 + if (!cell->anonymous_key) { 30 + key = rxrpc_get_null_key(cell->key_desc); 31 + if (!IS_ERR(key)) 32 + cell->anonymous_key = key; 33 + } 34 + mutex_unlock(&afs_key_lock); 35 + 36 + if (IS_ERR(key)) 37 + return PTR_ERR(key); 38 + 39 + _debug("anon key %p{%x}", 40 + cell->anonymous_key, key_serial(cell->anonymous_key)); 41 + return 0; 42 + } 19 43 20 44 /* 21 45 * get a key ··· 47 23 struct key *afs_request_key(struct afs_cell *cell) 48 24 { 49 25 struct key *key; 26 + int ret; 50 27 51 - _enter("{%x}", key_serial(cell->anonymous_key)); 28 + _enter("{%s}", cell->key_desc); 52 29 53 - _debug("key %s", cell->anonymous_key->description); 54 - key = request_key_net(&key_type_rxrpc, cell->anonymous_key->description, 30 + _debug("key %s", cell->key_desc); 31 + key = request_key_net(&key_type_rxrpc, cell->key_desc, 55 32 cell->net->net, NULL); 56 33 if (IS_ERR(key)) { 57 34 if (PTR_ERR(key) != -ENOKEY) { 58 35 _leave(" = %ld", PTR_ERR(key)); 59 36 return key; 37 + } 38 + 39 + if (!cell->anonymous_key) { 40 + ret = afs_alloc_anon_key(cell); 41 + if (ret < 0) 42 + return ERR_PTR(ret); 60 43 } 61 44 62 45 /* act as anonymous user */ ··· 83 52 { 84 53 struct key *key; 85 54 86 - _enter("{%x}", key_serial(cell->anonymous_key)); 55 + _enter("{%s}", cell->key_desc); 87 56 88 - _debug("key %s", cell->anonymous_key->description); 89 - key = request_key_net_rcu(&key_type_rxrpc, 90 - cell->anonymous_key->description, 57 + _debug("key %s", cell->key_desc); 58 + key = request_key_net_rcu(&key_type_rxrpc, cell->key_desc, 91 59 cell->net->net); 92 60 if (IS_ERR(key)) { 93 61 if (PTR_ERR(key) != -ENOKEY) { ··· 95 65 } 96 66 97 67 /* act as anonymous user */ 68 + if (!cell->anonymous_key) 69 + return NULL; /* Need to allocate */ 98 70 _leave(" = {%x} [anon]", key_serial(cell->anonymous_key)); 99 71 return key_get(cell->anonymous_key); 100 72 } else { ··· 440 408 441 409 if (mask & MAY_NOT_BLOCK) { 442 410 key = afs_request_key_rcu(vnode->volume->cell); 443 - if (IS_ERR(key)) 411 + if (IS_ERR_OR_NULL(key)) 444 412 return -ECHILD; 445 413 446 414 ret = -ECHILD;
+4 -3
fs/namespace.c
··· 5746 5746 5747 5747 if (kreq->mnt_ns_id) { 5748 5748 mnt_ns = lookup_mnt_ns(kreq->mnt_ns_id); 5749 + if (!mnt_ns) 5750 + return ERR_PTR(-ENOENT); 5749 5751 } else if (kreq->mnt_ns_fd) { 5750 5752 struct ns_common *ns; 5751 5753 ··· 5763 5761 return ERR_PTR(-EINVAL); 5764 5762 5765 5763 mnt_ns = to_mnt_ns(ns); 5764 + refcount_inc(&mnt_ns->passive); 5766 5765 } else { 5767 5766 mnt_ns = current->nsproxy->mnt_ns; 5767 + refcount_inc(&mnt_ns->passive); 5768 5768 } 5769 - if (!mnt_ns) 5770 - return ERR_PTR(-ENOENT); 5771 5769 5772 - refcount_inc(&mnt_ns->passive); 5773 5770 return mnt_ns; 5774 5771 } 5775 5772
+2 -2
fs/overlayfs/util.c
··· 1234 1234 goto err; 1235 1235 if (trap) 1236 1236 goto err_unlock; 1237 - if (work && work->d_parent != workdir) 1237 + if (work && (work->d_parent != workdir || d_unhashed(work))) 1238 1238 goto err_unlock; 1239 - if (upper && upper->d_parent != upperdir) 1239 + if (upper && (upper->d_parent != upperdir || d_unhashed(upper))) 1240 1240 goto err_unlock; 1241 1241 1242 1242 return 0;