Message ID | 20160108133104.GA5838@gondor.apana.org.au (mailing list archive) |
---|---|
State | Accepted |
Delegated to: | Herbert Xu |
Headers | show |
Hi Herbert, [auto build test ERROR on crypto/master] [also build test ERROR on v4.4-rc8 next-20160108] [if your patch is applied to the wrong git tree, please drop us a note to help improving the system] url: https://github.com/0day-ci/linux/commits/Herbert-Xu/crypto-hash-Add-crypto_ahash_has_setkey/20160108-213436 base: https://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6.git master config: x86_64-randconfig-i0-201601 (attached as .config) reproduce: # save the attached .config to linux build tree make ARCH=x86_64 All error/warnings (new ones prefixed by >>): crypto/algif_hash.c: In function 'hash_check_key': >> crypto/algif_hash.c:252:9: error: 'struct alg_sock' has no member named 'refcnt' if (ask->refcnt) ^ crypto/algif_hash.c:264:11: error: 'struct alg_sock' has no member named 'refcnt' if (!pask->refcnt++) ^ crypto/algif_hash.c:267:5: error: 'struct alg_sock' has no member named 'refcnt' ask->refcnt = 1; ^ crypto/algif_hash.c: In function 'hash_release_parent_nokey': crypto/algif_hash.c:407:10: error: 'struct alg_sock' has no member named 'refcnt' if (!ask->refcnt) { ^ crypto/algif_hash.c: At top level: >> crypto/algif_hash.c:486:2: error: unknown field 'accept_nokey' specified in initializer .accept_nokey = hash_accept_parent_nokey, ^ >> crypto/algif_hash.c:486:18: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types] .accept_nokey = hash_accept_parent_nokey, ^ crypto/algif_hash.c:486:18: note: (near initialization for 'algif_type_hash.setauthsize') >> crypto/algif_hash.c:488:2: error: unknown field 'ops_nokey' specified in initializer .ops_nokey = &algif_hash_ops_nokey, ^ crypto/algif_hash.c:488:15: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types] .ops_nokey = &algif_hash_ops_nokey, ^ crypto/algif_hash.c:488:15: note: (near initialization for 'algif_type_hash.owner') vim +252 crypto/algif_hash.c 246 struct sock *psk; 247 struct alg_sock *pask; 248 struct algif_hash_tfm *tfm; 249 struct sock *sk = sock->sk; 250 struct alg_sock *ask = alg_sk(sk); 251 > 252 if (ask->refcnt) 253 return 0; 254 255 psk = ask->parent; 256 pask = alg_sk(ask->parent); 257 tfm = pask->private; 258 259 err = -ENOKEY; 260 lock_sock(psk); 261 if (!tfm->has_key) 262 goto unlock; 263 264 if (!pask->refcnt++) 265 sock_hold(psk); 266 > 267 ask->refcnt = 1; 268 sock_put(psk); 269 270 err = 0; 271 272 unlock: 273 release_sock(psk); 274 275 return err; 276 } 277 278 static int hash_sendmsg_nokey(struct socket *sock, struct msghdr *msg, 279 size_t size) 280 { 281 int err; 282 283 err = hash_check_key(sock); 284 if (err) 285 return err; 286 287 return hash_sendmsg(sock, msg, size); 288 } 289 290 static ssize_t hash_sendpage_nokey(struct socket *sock, struct page *page, 291 int offset, size_t size, int flags) 292 { 293 int err; 294 295 err = hash_check_key(sock); 296 if (err) 297 return err; 298 299 return hash_sendpage(sock, page, offset, size, flags); 300 } 301 302 static int hash_recvmsg_nokey(struct socket *sock, struct msghdr *msg, 303 size_t ignored, int flags) 304 { 305 int err; 306 307 err = hash_check_key(sock); 308 if (err) 309 return err; 310 311 return hash_recvmsg(sock, msg, ignored, flags); 312 } 313 314 static int hash_accept_nokey(struct socket *sock, struct socket *newsock, 315 int flags) 316 { 317 int err; 318 319 err = hash_check_key(sock); 320 if (err) 321 return err; 322 323 return hash_accept(sock, newsock, flags); 324 } 325 326 static struct proto_ops algif_hash_ops_nokey = { 327 .family = PF_ALG, 328 329 .connect = sock_no_connect, 330 .socketpair = sock_no_socketpair, 331 .getname = sock_no_getname, 332 .ioctl = sock_no_ioctl, 333 .listen = sock_no_listen, 334 .shutdown = sock_no_shutdown, 335 .getsockopt = sock_no_getsockopt, 336 .mmap = sock_no_mmap, 337 .bind = sock_no_bind, 338 .setsockopt = sock_no_setsockopt, 339 .poll = sock_no_poll, 340 341 .release = af_alg_release, 342 .sendmsg = hash_sendmsg_nokey, 343 .sendpage = hash_sendpage_nokey, 344 .recvmsg = hash_recvmsg_nokey, 345 .accept = hash_accept_nokey, 346 }; 347 348 static void *hash_bind(const char *name, u32 type, u32 mask) 349 { 350 struct algif_hash_tfm *tfm; 351 struct crypto_ahash *hash; 352 353 tfm = kzalloc(sizeof(*tfm), GFP_KERNEL); 354 if (!tfm) 355 return ERR_PTR(-ENOMEM); 356 357 hash = crypto_alloc_ahash(name, type, mask); 358 if (IS_ERR(hash)) { 359 kfree(tfm); 360 return ERR_CAST(hash); 361 } 362 363 tfm->hash = hash; 364 365 return tfm; 366 } 367 368 static void hash_release(void *private) 369 { 370 struct algif_hash_tfm *tfm = private; 371 372 crypto_free_ahash(tfm->hash); 373 kfree(tfm); 374 } 375 376 static int hash_setkey(void *private, const u8 *key, unsigned int keylen) 377 { 378 struct algif_hash_tfm *tfm = private; 379 int err; 380 381 err = crypto_ahash_setkey(tfm->hash, key, keylen); 382 tfm->has_key = !err; 383 384 return err; 385 } 386 387 static void hash_sock_destruct_common(struct sock *sk) 388 { 389 struct alg_sock *ask = alg_sk(sk); 390 struct hash_ctx *ctx = ask->private; 391 392 sock_kzfree_s(sk, ctx->result, 393 crypto_ahash_digestsize(crypto_ahash_reqtfm(&ctx->req))); 394 sock_kfree_s(sk, ctx, ctx->len); 395 } 396 397 static void hash_sock_destruct(struct sock *sk) 398 { 399 hash_sock_destruct_common(sk); 400 af_alg_release_parent(sk); 401 } 402 403 static void hash_release_parent_nokey(struct sock *sk) 404 { 405 struct alg_sock *ask = alg_sk(sk); 406 > 407 if (!ask->refcnt) { 408 sock_put(ask->parent); 409 return; 410 } --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
On 01/08/2016 02:31 PM, Herbert Xu wrote: > Hash implementations that require a key may crash if you use > them without setting a key. This patch adds the necessary checks > so that if you do attempt to use them without a key that we return > -ENOKEY instead of proceeding. > > This patch also adds a compatibility path to support old applications > that do acept(2) before setkey. > > Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Reported-and-tested-by: Milan Broz <gmazyland@gmail.com> (tested both patches, ditto for previous skcipher series) Thanks, Milan -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c index b4c24fe..46637be 100644 --- a/crypto/algif_hash.c +++ b/crypto/algif_hash.c @@ -34,6 +34,11 @@ struct hash_ctx { struct ahash_request req; }; +struct algif_hash_tfm { + struct crypto_ahash *hash; + bool has_key; +}; + static int hash_sendmsg(struct socket *sock, struct msghdr *msg, size_t ignored) { @@ -235,22 +240,151 @@ static struct proto_ops algif_hash_ops = { .accept = hash_accept, }; +static int hash_check_key(struct socket *sock) +{ + int err; + struct sock *psk; + struct alg_sock *pask; + struct algif_hash_tfm *tfm; + struct sock *sk = sock->sk; + struct alg_sock *ask = alg_sk(sk); + + if (ask->refcnt) + return 0; + + psk = ask->parent; + pask = alg_sk(ask->parent); + tfm = pask->private; + + err = -ENOKEY; + lock_sock(psk); + if (!tfm->has_key) + goto unlock; + + if (!pask->refcnt++) + sock_hold(psk); + + ask->refcnt = 1; + sock_put(psk); + + err = 0; + +unlock: + release_sock(psk); + + return err; +} + +static int hash_sendmsg_nokey(struct socket *sock, struct msghdr *msg, + size_t size) +{ + int err; + + err = hash_check_key(sock); + if (err) + return err; + + return hash_sendmsg(sock, msg, size); +} + +static ssize_t hash_sendpage_nokey(struct socket *sock, struct page *page, + int offset, size_t size, int flags) +{ + int err; + + err = hash_check_key(sock); + if (err) + return err; + + return hash_sendpage(sock, page, offset, size, flags); +} + +static int hash_recvmsg_nokey(struct socket *sock, struct msghdr *msg, + size_t ignored, int flags) +{ + int err; + + err = hash_check_key(sock); + if (err) + return err; + + return hash_recvmsg(sock, msg, ignored, flags); +} + +static int hash_accept_nokey(struct socket *sock, struct socket *newsock, + int flags) +{ + int err; + + err = hash_check_key(sock); + if (err) + return err; + + return hash_accept(sock, newsock, flags); +} + +static struct proto_ops algif_hash_ops_nokey = { + .family = PF_ALG, + + .connect = sock_no_connect, + .socketpair = sock_no_socketpair, + .getname = sock_no_getname, + .ioctl = sock_no_ioctl, + .listen = sock_no_listen, + .shutdown = sock_no_shutdown, + .getsockopt = sock_no_getsockopt, + .mmap = sock_no_mmap, + .bind = sock_no_bind, + .setsockopt = sock_no_setsockopt, + .poll = sock_no_poll, + + .release = af_alg_release, + .sendmsg = hash_sendmsg_nokey, + .sendpage = hash_sendpage_nokey, + .recvmsg = hash_recvmsg_nokey, + .accept = hash_accept_nokey, +}; + static void *hash_bind(const char *name, u32 type, u32 mask) { - return crypto_alloc_ahash(name, type, mask); + struct algif_hash_tfm *tfm; + struct crypto_ahash *hash; + + tfm = kzalloc(sizeof(*tfm), GFP_KERNEL); + if (!tfm) + return ERR_PTR(-ENOMEM); + + hash = crypto_alloc_ahash(name, type, mask); + if (IS_ERR(hash)) { + kfree(tfm); + return ERR_CAST(hash); + } + + tfm->hash = hash; + + return tfm; } static void hash_release(void *private) { - crypto_free_ahash(private); + struct algif_hash_tfm *tfm = private; + + crypto_free_ahash(tfm->hash); + kfree(tfm); } static int hash_setkey(void *private, const u8 *key, unsigned int keylen) { - return crypto_ahash_setkey(private, key, keylen); + struct algif_hash_tfm *tfm = private; + int err; + + err = crypto_ahash_setkey(tfm->hash, key, keylen); + tfm->has_key = !err; + + return err; } -static void hash_sock_destruct(struct sock *sk) +static void hash_sock_destruct_common(struct sock *sk) { struct alg_sock *ask = alg_sk(sk); struct hash_ctx *ctx = ask->private; @@ -258,15 +392,40 @@ static void hash_sock_destruct(struct sock *sk) sock_kzfree_s(sk, ctx->result, crypto_ahash_digestsize(crypto_ahash_reqtfm(&ctx->req))); sock_kfree_s(sk, ctx, ctx->len); +} + +static void hash_sock_destruct(struct sock *sk) +{ + hash_sock_destruct_common(sk); af_alg_release_parent(sk); } -static int hash_accept_parent(void *private, struct sock *sk) +static void hash_release_parent_nokey(struct sock *sk) +{ + struct alg_sock *ask = alg_sk(sk); + + if (!ask->refcnt) { + sock_put(ask->parent); + return; + } + + af_alg_release_parent(sk); +} + +static void hash_sock_destruct_nokey(struct sock *sk) +{ + hash_sock_destruct_common(sk); + hash_release_parent_nokey(sk); +} + +static int hash_accept_parent_common(void *private, struct sock *sk) { struct hash_ctx *ctx; struct alg_sock *ask = alg_sk(sk); - unsigned len = sizeof(*ctx) + crypto_ahash_reqsize(private); - unsigned ds = crypto_ahash_digestsize(private); + struct algif_hash_tfm *tfm = private; + struct crypto_ahash *hash = tfm->hash; + unsigned len = sizeof(*ctx) + crypto_ahash_reqsize(hash); + unsigned ds = crypto_ahash_digestsize(hash); ctx = sock_kmalloc(sk, len, GFP_KERNEL); if (!ctx) @@ -286,7 +445,7 @@ static int hash_accept_parent(void *private, struct sock *sk) ask->private = ctx; - ahash_request_set_tfm(&ctx->req, private); + ahash_request_set_tfm(&ctx->req, hash); ahash_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG, af_alg_complete, &ctx->completion); @@ -295,12 +454,38 @@ static int hash_accept_parent(void *private, struct sock *sk) return 0; } +static int hash_accept_parent(void *private, struct sock *sk) +{ + struct algif_hash_tfm *tfm = private; + + if (!tfm->has_key && crypto_ahash_has_setkey(tfm->hash)) + return -ENOKEY; + + return hash_accept_parent_common(private, sk); +} + +static int hash_accept_parent_nokey(void *private, struct sock *sk) +{ + int err; + + err = hash_accept_parent_common(private, sk); + if (err) + goto out; + + sk->sk_destruct = hash_sock_destruct_nokey; + +out: + return err; +} + static const struct af_alg_type algif_type_hash = { .bind = hash_bind, .release = hash_release, .setkey = hash_setkey, .accept = hash_accept_parent, + .accept_nokey = hash_accept_parent_nokey, .ops = &algif_hash_ops, + .ops_nokey = &algif_hash_ops_nokey, .name = "hash", .owner = THIS_MODULE };
Hash implementations that require a key may crash if you use them without setting a key. This patch adds the necessary checks so that if you do attempt to use them without a key that we return -ENOKEY instead of proceeding. This patch also adds a compatibility path to support old applications that do acept(2) before setkey. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>