diff options
author | Ulrich Drepper <drepper@redhat.com> | 1998-07-21 13:58:40 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 1998-07-21 13:58:40 +0000 |
commit | c13de8877bb60d2a7cc23e6c36e6ed1b25b3b624 (patch) | |
tree | c3ea38566facfffd85986f89060eb596fcc4ab5d | |
parent | 2b25f93f7ad09ec1c2b93e07ceae577b56b44a80 (diff) | |
download | glibc-c13de8877bb60d2a7cc23e6c36e6ed1b25b3b624.tar.gz glibc-c13de8877bb60d2a7cc23e6c36e6ed1b25b3b624.tar.xz glibc-c13de8877bb60d2a7cc23e6c36e6ed1b25b3b624.zip |
Update.
1998-07-21 16:08 -0400 Zack Weinberg <zack@rabi.phys.columbia.edu> * sysdeps/unix/sysv/linux/sendmsg.c: If passing a SCM_CREDS message, copy the buffer and resize it to what the kernel wants to see. Bug found and analyzed by Thorsten Kukuk <kukuk@weber-eb.uni-paderborn.de>
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/sendmsg.c | 100 |
2 files changed, 74 insertions, 33 deletions
diff --git a/ChangeLog b/ChangeLog index 2e6cc830e1..a741080f6d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +1998-07-21 16:08 -0400 Zack Weinberg <zack@rabi.phys.columbia.edu> + + * sysdeps/unix/sysv/linux/sendmsg.c: If passing a SCM_CREDS + message, copy the buffer and resize it to what the kernel + wants to see. Bug found and analyzed by Thorsten Kukuk + <kukuk@weber-eb.uni-paderborn.de> + 1998-07-20 Jose M. Moya <josem@gnu.org> * hurd/hurdmsg.c (_S_msg_get_env_variable): Copy getenv return diff --git a/sysdeps/unix/sysv/linux/sendmsg.c b/sysdeps/unix/sysv/linux/sendmsg.c index 16774c48b1..c0f009d0ac 100644 --- a/sysdeps/unix/sysv/linux/sendmsg.c +++ b/sysdeps/unix/sysv/linux/sendmsg.c @@ -18,6 +18,8 @@ #include <sys/socket.h> #include <errno.h> +#include <stdlib.h> +#include <string.h> #include <unistd.h> #include <asm/posix_types.h> @@ -25,12 +27,24 @@ /* The kernel expects this structure in SCM_CREDS messages. * Note: sizeof(struct __kernel_ucred) <= sizeof(struct cmsgcred) must hold. */ -struct __kernel_ucred -{ - __kernel_pid_t pid; - __kernel_uid_t uid; - __kernel_gid_t gid; -}; +struct kernel_ucred + { + __kernel_pid_t pid; + __kernel_uid_t uid; + __kernel_gid_t gid; + }; + +struct credmsg + { + struct cmsghdr cm; + struct cmsgcred cc; + }; + +struct kcredmsg + { + struct cmsghdr cm; + struct kernel_ucred cc; + }; extern int __syscall_sendmsg (int, const struct msghdr *, int); @@ -39,51 +53,71 @@ extern int __syscall_sendmsg (int, const struct msghdr *, int); int __libc_sendmsg (int fd, const struct msghdr *message, int flags) { + struct msghdr m; + char *buf, *a, *b; + struct credmsg *cred = 0; + struct kcredmsg *kcred; struct cmsghdr *cm; - struct cmsgcred *cc; - struct __kernel_ucred *u; + long int offset = 0; pid_t pid; /* Preprocess the message control block for SCM_CREDS. */ - cm = CMSG_FIRSTHDR (message); - while (cm) + if (message->msg_controllen) { - if (cm->cmsg_type == SCM_CREDS) + cm = CMSG_FIRSTHDR (message); + while (cm) { - if (cm->cmsg_len < CMSG_SPACE (sizeof (struct cmsgcred))) + if (cm->cmsg_type == SCM_CREDS) { - __set_errno (EINVAL); - return -1; + if (cred || + cm->cmsg_len < CMSG_LEN (sizeof (struct cmsgcred))) + { + __set_errno (EINVAL); + return -1; + } + else + { + cred = (struct credmsg *) cm; + offset = (char *) cm - (char *) message->msg_control; + } } + cm = CMSG_NXTHDR ((struct msghdr *) message, cm); + } + + if (cred) + { + buf = alloca (message->msg_controllen); + memcpy (buf, message->msg_control, message->msg_controllen); + kcred = (struct kcredmsg *) (buf + offset); + a = (char *) kcred + CMSG_LEN (sizeof (struct kernel_ucred)); + b = (char *) kcred + CMSG_LEN (sizeof (struct cmsgcred)); + memmove (a, b, message->msg_controllen - (b - buf)); + + kcred->cm.cmsg_len = CMSG_LEN (sizeof (struct kernel_ucred)); - u = (struct __kernel_ucred *) CMSG_DATA (cm); - cc = (struct cmsgcred *) CMSG_DATA (cm); /* Linux expects the calling process to pass in its credentials, and sanity checks them. You can send real, effective, or set- uid and gid. If the user hasn't filled in the buffer, we default to real uid and gid. */ pid = __getpid (); - if (cc->cmcred_pid != pid) - { - u->pid = pid; - u->uid = __getuid (); - u->gid = __getgid (); - } + if (cred->cc.cmcred_pid != pid) + { + kcred->cc.pid = pid; + kcred->cc.uid = __getuid (); + kcred->cc.gid = __getgid (); + } else - { - struct __kernel_ucred v; - v.pid = cc->cmcred_pid; - v.uid = cc->cmcred_uid; - v.gid = cc->cmcred_gid; - u->pid = v.pid; - u->uid = v.uid; - u->gid = v.gid; - } + { + kcred->cc.uid = cred->cc.cmcred_uid; + kcred->cc.gid = cred->cc.cmcred_gid; + } + memcpy (&m, message, sizeof (struct msghdr)); + m.msg_control = buf; + m.msg_controllen -= b - a; + return __syscall_sendmsg (fd, &m, flags); } - cm = CMSG_NXTHDR ((struct msghdr *) message, cm); } - return __syscall_sendmsg (fd, message, flags); } |