Re: [PATCH 2/2] keys: Allow request_key upcalls from a container to be intercepted

From: kernel test robot
Date: Thu Feb 04 2021 - 15:01:38 EST


Hi David,

I love your patch! Perhaps something to improve:

[auto build test WARNING on cgroup/for-next]
[also build test WARNING on dhowells-fs/fscache-next linus/master v5.11-rc6]
[cannot apply to security/next-testing tip/timers/core next-20210125]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url: https://github.com/0day-ci/linux/commits/David-Howells/keys-request_key-interception-in-containers/20210205-015946
base: https://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git for-next
config: powerpc64-randconfig-s031-20210204 (attached as .config)
compiler: powerpc-linux-gcc (GCC) 9.3.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# apt-get install sparse
# sparse version: v0.6.3-215-g0fb77bb6-dirty
# https://github.com/0day-ci/linux/commit/6d049eb50238910e375143259391790a8b69ebc6
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review David-Howells/keys-request_key-interception-in-containers/20210205-015946
git checkout 6d049eb50238910e375143259391790a8b69ebc6
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' ARCH=powerpc64

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@xxxxxxxxx>


"sparse warnings: (new ones prefixed by >>)"
>> security/keys/service.c:101:40: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected char const *type @@ got char const [noderef] __user *type_name @@
security/keys/service.c:101:40: sparse: expected char const *type
security/keys/service.c:101:40: sparse: got char const [noderef] __user *type_name
>> security/keys/service.c:177:9: sparse: sparse: incompatible types in comparison expression (different address spaces):
>> security/keys/service.c:177:9: sparse: struct hlist_node [noderef] __rcu *
>> security/keys/service.c:177:9: sparse: struct hlist_node *

vim +101 security/keys/service.c

61
62 /*
63 * Allocate a service record.
64 */
65 static struct request_key_service *alloc_key_service(key_serial_t queue_keyring,
66 const char __user *type_name,
67 unsigned int ns_mask)
68 {
69 struct request_key_service *svc;
70 struct key_type *type;
71 key_ref_t key_ref;
72 int ret;
73 u8 selectivity = 0;
74
75 svc = kzalloc(sizeof(struct request_key_service), GFP_KERNEL);
76 if (!svc)
77 return ERR_PTR(-ENOMEM);
78
79 if (queue_keyring != 0) {
80 key_ref = lookup_user_key(queue_keyring, 0, KEY_NEED_SEARCH);
81 if (IS_ERR(key_ref)) {
82 ret = PTR_ERR(key_ref);
83 goto err_svc;
84 }
85
86 svc->queue_keyring = key_ref_to_ptr(key_ref);
87 }
88
89 /* Save the matching criteria. Anything the caller doesn't care about
90 * we leave as NULL.
91 */
92 if (type_name) {
93 ret = strncpy_from_user(svc->type, type_name, sizeof(svc->type));
94 if (ret < 0)
95 goto err_keyring;
96 if (ret >= sizeof(svc->type)) {
97 ret = -EINVAL;
98 goto err_keyring;
99 }
100
> 101 type = key_type_lookup(type_name);
102 if (IS_ERR(type)) {
103 ret = -EINVAL;
104 goto err_keyring;
105 }
106 memcpy(svc->type, type->name, sizeof(svc->type));
107 key_type_put(type);
108 }
109
110 if (ns_mask & KEY_SERVICE_NS_UTS) {
111 svc->uts_ns = get_ns_tag(current->nsproxy->uts_ns->ns.tag);
112 selectivity++;
113 }
114 if (ns_mask & KEY_SERVICE_NS_IPC) {
115 svc->ipc_ns = get_ns_tag(current->nsproxy->ipc_ns->ns.tag);
116 selectivity++;
117 }
118 if (ns_mask & KEY_SERVICE_NS_MNT) {
119 svc->mnt_ns = get_ns_tag(current->nsproxy->mnt_ns->ns.tag);
120 selectivity++;
121 }
122 if (ns_mask & KEY_SERVICE_NS_PID) {
123 svc->pid_ns = get_ns_tag(task_active_pid_ns(current)->ns.tag);
124 selectivity++;
125 }
126 if (ns_mask & KEY_SERVICE_NS_NET) {
127 svc->net_ns = get_ns_tag(current->nsproxy->net_ns->ns.tag);
128 selectivity++;
129 }
130 if (ns_mask & KEY_SERVICE_NS_CGROUP) {
131 svc->cgroup_ns = get_ns_tag(current->nsproxy->cgroup_ns->ns.tag);
132 selectivity++;
133 }
134
135 svc->selectivity = selectivity;
136 return svc;
137
138 err_keyring:
139 key_put(svc->queue_keyring);
140 err_svc:
141 kfree(svc);
142 return ERR_PTR(ret);
143 }
144
145 /*
146 * Install a request_key service into the user namespace's list
147 */
148 static int install_key_service(struct user_namespace *user_ns,
149 struct request_key_service *svc)
150 {
151 struct request_key_service *p;
152 struct hlist_node **pp;
153 int ret = 0;
154
155 spin_lock(&user_ns->request_key_services_lock);
156
157 /* The services list is kept in order of selectivity. The more exact
158 * matches a service requires, the earlier it is in the list.
159 */
160 for (pp = &user_ns->request_key_services.first; *pp; pp = &(*pp)->next) {
161 p = hlist_entry(*pp, struct request_key_service, user_ns_link);
162 if (p->selectivity < svc->selectivity)
163 goto insert_before;
164 if (p->selectivity > svc->selectivity)
165 continue;
166 if (memcmp(p->type, svc->type, sizeof(p->type)) == 0 &&
167 p->uts_ns == svc->uts_ns &&
168 p->ipc_ns == svc->ipc_ns &&
169 p->mnt_ns == svc->mnt_ns &&
170 p->pid_ns == svc->pid_ns &&
171 p->net_ns == svc->net_ns &&
172 p->cgroup_ns == svc->cgroup_ns)
173 goto duplicate;
174 }
175
176 svc->user_ns_link.pprev = pp;
> 177 rcu_assign_pointer(*pp, &svc->user_ns_link);
178 goto out;
179
180 insert_before:
181 hlist_add_before_rcu(&svc->user_ns_link, &p->user_ns_link);
182 goto out;
183
184 duplicate:
185 free_key_service(svc);
186 ret = -EEXIST;
187 out:
188 spin_unlock(&user_ns->request_key_services_lock);
189 return ret;
190 }
191

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@xxxxxxxxxxxx

Attachment: .config.gz
Description: application/gzip