Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

nfsd: don't alloc under spinlock in rpc_parse_scope_id

Dan Carpenter says:

The patch d20c11d86d8f: "nfsd: Protect session creation and client
confirm using client_lock" from Jul 30, 2014, leads to the following
Smatch static checker warning:

net/sunrpc/addr.c:178 rpc_parse_scope_id()
warn: sleeping in atomic context

Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Fixes: d20c11d86d8f ("nfsd: Protect session creation and client...")
Signed-off-by: J. Bruce Fields <bfields@redhat.com>

+16 -20
+16 -20
net/sunrpc/addr.c
··· 162 162 const size_t buflen, const char *delim, 163 163 struct sockaddr_in6 *sin6) 164 164 { 165 - char *p; 165 + char p[IPV6_SCOPE_ID_LEN + 1]; 166 166 size_t len; 167 + u32 scope_id = 0; 168 + struct net_device *dev; 167 169 168 170 if ((buf + buflen) == delim) 169 171 return 1; ··· 177 175 return 0; 178 176 179 177 len = (buf + buflen) - delim - 1; 180 - p = kmemdup_nul(delim + 1, len, GFP_KERNEL); 181 - if (p) { 182 - u32 scope_id = 0; 183 - struct net_device *dev; 178 + if (len > IPV6_SCOPE_ID_LEN) 179 + return 0; 184 180 185 - dev = dev_get_by_name(net, p); 186 - if (dev != NULL) { 187 - scope_id = dev->ifindex; 188 - dev_put(dev); 189 - } else { 190 - if (kstrtou32(p, 10, &scope_id) != 0) { 191 - kfree(p); 192 - return 0; 193 - } 194 - } 181 + memcpy(p, delim + 1, len); 182 + p[len] = 0; 195 183 196 - kfree(p); 197 - 198 - sin6->sin6_scope_id = scope_id; 199 - return 1; 184 + dev = dev_get_by_name(net, p); 185 + if (dev != NULL) { 186 + scope_id = dev->ifindex; 187 + dev_put(dev); 188 + } else { 189 + if (kstrtou32(p, 10, &scope_id) != 0) 190 + return 0; 200 191 } 201 192 202 - return 0; 193 + sin6->sin6_scope_id = scope_id; 194 + return 1; 203 195 } 204 196 205 197 static size_t rpc_pton6(struct net *net, const char *buf, const size_t buflen,