diff options
author | Andrew G. Morgan <morgan@kernel.org> | 2021-11-07 15:09:13 -0800 |
---|---|---|
committer | Andrew G. Morgan <morgan@kernel.org> | 2021-11-07 15:09:13 -0800 |
commit | 95085598764ca6c874dc1ee48364dbd2921fc000 (patch) | |
tree | 3cbe314437e22d76058cdbc5b818e8a898f10266 | |
parent | 2b763ab706891255e8cef9f36ca023e32f5d5991 (diff) | |
download | libcap-95085598764ca6c874dc1ee48364dbd2921fc000.tar.gz |
Use calloc'd memory for unix domain socket exchange.
This seems more stable for passing file descriptor from privileged
child to unprivileged parent.
Signed-off-by: Andrew G. Morgan <morgan@kernel.org>
-rw-r--r-- | contrib/capso/capso.c | 67 |
1 files changed, 43 insertions, 24 deletions
diff --git a/contrib/capso/capso.c b/contrib/capso/capso.c index 13710e2..3f2f3ba 100644 --- a/contrib/capso/capso.c +++ b/contrib/capso/capso.c @@ -47,16 +47,20 @@ static char *where_am_i(void) */ static int try_bind80(const char *hostname) { - struct addrinfo conf, *detail = NULL; + struct addrinfo *conf, *detail = NULL; int err, ret = -1, one = 1; - memset(&conf, 0, sizeof(conf)); - conf.ai_family = PF_UNSPEC; - conf.ai_socktype = SOCK_STREAM; - conf.ai_protocol = 0; - conf.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; + conf = calloc(1, sizeof(*conf)); + if (conf == NULL) { + return -1; + } + + conf->ai_family = PF_UNSPEC; + conf->ai_socktype = SOCK_STREAM; + conf->ai_protocol = 0; + conf->ai_flags = AI_PASSIVE | AI_ADDRCONFIG; - err = getaddrinfo(hostname, "80", &conf, &detail); + err = getaddrinfo(hostname, "80", conf, &detail); if (err != 0) { goto done; } @@ -78,10 +82,11 @@ static int try_bind80(const char *hostname) goto done; } -done: + done: if (detail != NULL) { freeaddrinfo(detail); } + free(conf); return ret; } @@ -116,23 +121,33 @@ static int set_fd3(void *detail) */ int bind80(const char *hostname) { + cap_launch_t helper; + pid_t child; char const *args[3]; char *path; int fd, ignored; int sp[2]; - struct iovec iov[1]; char junk[1]; const int rec_buf_len = CMSG_SPACE(sizeof(int)); char *rec_buf[CMSG_SPACE(sizeof(int))]; - struct msghdr msg; - cap_launch_t helper; - pid_t child; + struct iovec *iov; + struct msghdr *msg; fd = try_bind80(hostname); if (fd >= 0) { return fd; } + iov = calloc(1, sizeof(struct iovec)); + if (iov == NULL) { + return -1; + } + msg = calloc(1, sizeof(struct msghdr)); + if (msg == NULL) { + free(iov); + return -1; + } + /* * Initial attempt didn't work, so try launching the shared * library as an executable and getting it to yield a bound @@ -141,7 +156,7 @@ int bind80(const char *hostname) path = where_am_i(); if (path == NULL) { perror("unable to find self"); - return -1; + goto drop_alloc; } args[0] = "bind80-helper"; @@ -168,27 +183,31 @@ int bind80(const char *hostname) iov[0].iov_base = junk; iov[0].iov_len = 1; - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = iov; - msg.msg_iovlen = 1; - msg.msg_control = rec_buf; - msg.msg_controllen = rec_buf_len; + msg->msg_name = NULL; + msg->msg_namelen = 0; + msg->msg_iov = iov; + msg->msg_iovlen = 1; + msg->msg_control = rec_buf; + msg->msg_controllen = rec_buf_len; - if (recvmsg(sp[0], &msg, 0) != -1) { - fd = * (int *) CMSG_DATA(CMSG_FIRSTHDR(&msg)); + if (recvmsg(sp[0], msg, 0) != -1) { + fd = * (int *) CMSG_DATA(CMSG_FIRSTHDR(msg)); } waitpid(child, &ignored, 0); -drop_sp: + drop_sp: close(sp[0]); -drop_helper: + drop_helper: cap_free(helper); -drop_path: + drop_path: free(path); + drop_alloc: + free(msg); + free(iov); + return fd; } |