Test Case: ---------
$ cat aa-refcnt-af_alg.c #include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <linux/if_alg.h>
int main() { int sockfd; struct sockaddr_alg sa;
/* Setup the crypto API socket */ sockfd = socket(AF_ALG, SOCK_SEQPACKET, 0); if (sockfd < 0) { perror("socket"); return 1; }
memset(&sa, 0, sizeof(sa)); sa.salg_family = AF_ALG; strcpy((char *) sa.salg_type, "rng"); strcpy((char *) sa.salg_name, "stdrng");
if (bind(sockfd, (struct sockaddr *) &sa, sizeof(sa)) < 0) { perror("bind"); return 1; }
/* Accept a "connection" and close it; repeat. */ while (!close(accept(sockfd, NULL, 0)));
return 0; }
$ gcc -o aa-refcnt-af_alg aa-refcnt-af_alg.c
$ ./aa-refcnt-af_alg <a few hours later>
[ 9928.475953] refcount_t overflow at apparmor_sk_clone_security+0x37/0x70 in aa-refcnt-af_alg[1322], uid/euid: 1000/1000 ... [ 9928.507443] RIP: 0010:apparmor_sk_clone_security+0x37/0x70 ... [ 9928.514286] security_sk_clone+0x33/0x50 [ 9928.514807] af_alg_accept+0x81/0x1c0 [af_alg] [ 9928.516091] alg_accept+0x15/0x20 [af_alg] [ 9928.516682] SYSC_accept4+0xff/0x210 [ 9928.519609] SyS_accept+0x10/0x20 [ 9928.520190] do_syscall_64+0x73/0x130 [ 9928.520808] entry_SYSCALL_64_after_hwframe+0x3d/0xa2
Note that other messages may be seen, not just overflow, depending on the value being incremented by kref_get(); on another run:
[ 7273.182666] refcount_t: saturated; leaking memory. ... [ 7273.185789] refcount_t: underflow; use-after-free.
Test Case:
---------
$ cat aa-refcnt-af_alg.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <linux/if_alg.h>
int main() {
int sockfd;
struct sockaddr_alg sa;
/* Setup the crypto API socket */
perror( "socket" );
sockfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
if (sockfd < 0) {
return 1;
}
memset(&sa, 0, sizeof(sa));
sa.salg_family = AF_ALG;
strcpy((char *) sa.salg_type, "rng");
strcpy((char *) sa.salg_name, "stdrng");
if (bind(sockfd, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
perror( "bind") ;
return 1;
}
/* Accept a "connection" and close it; repeat. */ accept( sockfd, NULL, 0)));
while (!close(
return 0;
}
$ gcc -o aa-refcnt-af_alg aa-refcnt-af_alg.c
$ ./aa-refcnt-af_alg
<a few hours later>
[ 9928.475953] refcount_t overflow at apparmor_ sk_clone_ security+ 0x37/0x70 in aa-refcnt- af_alg[ 1322], uid/euid: 1000/1000 sk_clone_ security+ 0x37/0x70 sk_clone+ 0x33/0x50 accept+ 0x81/0x1c0 [af_alg] 0x15/0x20 [af_alg] 0xff/0x210 0x10/0x20 64+0x73/ 0x130 64_after_ hwframe+ 0x3d/0xa2
...
[ 9928.507443] RIP: 0010:apparmor_
...
[ 9928.514286] security_
[ 9928.514807] af_alg_
[ 9928.516091] alg_accept+
[ 9928.516682] SYSC_accept4+
[ 9928.519609] SyS_accept+
[ 9928.520190] do_syscall_
[ 9928.520808] entry_SYSCALL_
Note that other messages may be seen, not just overflow, depending on
the value being incremented by kref_get(); on another run:
[ 7273.182666] refcount_t: saturated; leaking memory.
...
[ 7273.185789] refcount_t: underflow; use-after-free.