diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2009-04-23 19:32:48 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2009-04-28 13:54:29 -0400 |
commit | e7942b9f2586fb15e1b898acc7c198ffd60aee4e (patch) | |
tree | eda6f5323a320ae59fe33f13b0c4bbd857eac7c6 /net | |
parent | 8435d34dbbe75678c3cdad3d53b1e7996a79b3bf (diff) |
SUNRPC: Switch one_sock_name() to use snprintf()
Use snprintf() in one_sock_name() to prevent overflowing the output
buffer. If the name doesn't fit in the buffer, the buffer is filled
in with an empty string, and -ENAMETOOLONG is returned.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Diffstat (limited to 'net')
-rw-r--r-- | net/sunrpc/svcsock.c | 25 |
1 files changed, 18 insertions, 7 deletions
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 032b52ea9541..61d4a3281f94 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -240,22 +240,27 @@ out: | |||
240 | /* | 240 | /* |
241 | * Report socket names for nfsdfs | 241 | * Report socket names for nfsdfs |
242 | */ | 242 | */ |
243 | static int one_sock_name(char *buf, struct svc_sock *svsk) | 243 | static int svc_one_sock_name(struct svc_sock *svsk, char *buf, int remaining) |
244 | { | 244 | { |
245 | int len; | 245 | int len; |
246 | 246 | ||
247 | switch(svsk->sk_sk->sk_family) { | 247 | switch(svsk->sk_sk->sk_family) { |
248 | case AF_INET: | 248 | case PF_INET: |
249 | len = sprintf(buf, "ipv4 %s %pI4 %d\n", | 249 | len = snprintf(buf, remaining, "ipv4 %s %pI4 %d\n", |
250 | svsk->sk_sk->sk_protocol == IPPROTO_UDP ? | 250 | svsk->sk_sk->sk_protocol == IPPROTO_UDP ? |
251 | "udp" : "tcp", | 251 | "udp" : "tcp", |
252 | &inet_sk(svsk->sk_sk)->rcv_saddr, | 252 | &inet_sk(svsk->sk_sk)->rcv_saddr, |
253 | inet_sk(svsk->sk_sk)->num); | 253 | inet_sk(svsk->sk_sk)->num); |
254 | break; | 254 | break; |
255 | default: | 255 | default: |
256 | len = sprintf(buf, "*unknown-%d*\n", | 256 | len = snprintf(buf, remaining, "*unknown-%d*\n", |
257 | svsk->sk_sk->sk_family); | 257 | svsk->sk_sk->sk_family); |
258 | } | 258 | } |
259 | |||
260 | if (len >= remaining) { | ||
261 | *buf = '\0'; | ||
262 | return -ENAMETOOLONG; | ||
263 | } | ||
259 | return len; | 264 | return len; |
260 | } | 265 | } |
261 | 266 | ||
@@ -282,15 +287,21 @@ int svc_sock_names(struct svc_serv *serv, char *buf, const size_t buflen, | |||
282 | 287 | ||
283 | if (!serv) | 288 | if (!serv) |
284 | return 0; | 289 | return 0; |
290 | |||
285 | spin_lock_bh(&serv->sv_lock); | 291 | spin_lock_bh(&serv->sv_lock); |
286 | list_for_each_entry(svsk, &serv->sv_permsocks, sk_xprt.xpt_list) { | 292 | list_for_each_entry(svsk, &serv->sv_permsocks, sk_xprt.xpt_list) { |
287 | int onelen = one_sock_name(buf+len, svsk); | 293 | int onelen = svc_one_sock_name(svsk, buf + len, buflen - len); |
288 | if (toclose && strcmp(toclose, buf+len) == 0) | 294 | if (onelen < 0) { |
295 | len = onelen; | ||
296 | break; | ||
297 | } | ||
298 | if (toclose && strcmp(toclose, buf + len) == 0) | ||
289 | closesk = svsk; | 299 | closesk = svsk; |
290 | else | 300 | else |
291 | len += onelen; | 301 | len += onelen; |
292 | } | 302 | } |
293 | spin_unlock_bh(&serv->sv_lock); | 303 | spin_unlock_bh(&serv->sv_lock); |
304 | |||
294 | if (closesk) | 305 | if (closesk) |
295 | /* Should unregister with portmap, but you cannot | 306 | /* Should unregister with portmap, but you cannot |
296 | * unregister just one protocol... | 307 | * unregister just one protocol... |
@@ -1195,7 +1206,7 @@ int svc_addsock(struct svc_serv *serv, const int fd, char *name_return, | |||
1195 | sockfd_put(so); | 1206 | sockfd_put(so); |
1196 | return err; | 1207 | return err; |
1197 | } | 1208 | } |
1198 | return one_sock_name(name_return, svsk); | 1209 | return svc_one_sock_name(svsk, name_return, len); |
1199 | } | 1210 | } |
1200 | EXPORT_SYMBOL_GPL(svc_addsock); | 1211 | EXPORT_SYMBOL_GPL(svc_addsock); |
1201 | 1212 | ||