aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew G. Morgan <morgan@kernel.org>2021-11-07 15:09:13 -0800
committerAndrew G. Morgan <morgan@kernel.org>2021-11-07 15:09:13 -0800
commit95085598764ca6c874dc1ee48364dbd2921fc000 (patch)
tree3cbe314437e22d76058cdbc5b818e8a898f10266
parent2b763ab706891255e8cef9f36ca023e32f5d5991 (diff)
downloadlibcap-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.c67
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;
}