diff options
Diffstat (limited to 'sys/compat/linux')
-rw-r--r-- | sys/compat/linux/linux_misc.c | 41 | ||||
-rw-r--r-- | sys/compat/linux/linux_netlink.c | 37 | ||||
-rw-r--r-- | sys/compat/linux/linux_socket.c | 12 | ||||
-rw-r--r-- | sys/compat/linux/linux_uid16.c | 39 |
4 files changed, 55 insertions, 74 deletions
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index 5e32353c6b8e..0925ffb64480 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -1028,24 +1028,24 @@ linux_nice(struct thread *td, struct linux_nice_args *args) int linux_setgroups(struct thread *td, struct linux_setgroups_args *args) { + const int ngrp = args->gidsetsize; struct ucred *newcred, *oldcred; l_gid_t *linux_gidset; - int ngrp, error; + int error; struct proc *p; - ngrp = args->gidsetsize; - if (ngrp < 0 || ngrp >= ngroups_max) + if (ngrp < 0 || ngrp > ngroups_max) return (EINVAL); linux_gidset = malloc(ngrp * sizeof(*linux_gidset), M_LINUX, M_WAITOK); error = copyin(args->grouplist, linux_gidset, ngrp * sizeof(l_gid_t)); if (error) goto out; + newcred = crget(); crextend(newcred, ngrp); p = td->td_proc; PROC_LOCK(p); - oldcred = p->p_ucred; - crcopy(newcred, oldcred); + oldcred = crcopysafe(p, newcred); if ((error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS)) != 0) { PROC_UNLOCK(p); @@ -1071,34 +1071,29 @@ out: int linux_getgroups(struct thread *td, struct linux_getgroups_args *args) { - struct ucred *cred; + const struct ucred *const cred = td->td_ucred; l_gid_t *linux_gidset; - gid_t *bsd_gidset; - int bsd_gidsetsz, ngrp, error; + int ngrp, error; - cred = td->td_ucred; - bsd_gidset = cred->cr_groups; - bsd_gidsetsz = cred->cr_ngroups; + ngrp = args->gidsetsize; - if ((ngrp = args->gidsetsize) == 0) { - td->td_retval[0] = bsd_gidsetsz; + if (ngrp == 0) { + td->td_retval[0] = cred->cr_ngroups; return (0); } - - if (ngrp < bsd_gidsetsz) + if (ngrp < cred->cr_ngroups) return (EINVAL); - ngrp = 0; - linux_gidset = malloc(bsd_gidsetsz * sizeof(*linux_gidset), - M_LINUX, M_WAITOK); - while (ngrp < bsd_gidsetsz) { - linux_gidset[ngrp] = bsd_gidset[ngrp]; - ngrp++; - } + ngrp = cred->cr_ngroups; + + linux_gidset = malloc(ngrp * sizeof(*linux_gidset), M_LINUX, M_WAITOK); + for (int i = 0; i < ngrp; ++i) + linux_gidset[i] = cred->cr_groups[i]; error = copyout(linux_gidset, args->grouplist, ngrp * sizeof(l_gid_t)); free(linux_gidset, M_LINUX); - if (error) + + if (error != 0) return (error); td->td_retval[0] = ngrp; diff --git a/sys/compat/linux/linux_netlink.c b/sys/compat/linux/linux_netlink.c index f51838ee00d7..6aeafe84adc6 100644 --- a/sys/compat/linux/linux_netlink.c +++ b/sys/compat/linux/linux_netlink.c @@ -563,22 +563,15 @@ nlmsg_to_linux(struct nlmsghdr *hdr, struct nlpcb *nlp, struct nl_writer *nw) } } -static bool -nlmsgs_to_linux(struct nl_writer *nw, struct nlpcb *nlp) +static struct nl_buf * +nlmsgs_to_linux(struct nl_buf *orig, struct nlpcb *nlp) { - struct nl_buf *nb, *orig; - u_int offset, msglen, orig_messages; - - RT_LOG(LOG_DEBUG3, "%p: in %u bytes %u messages", __func__, - nw->buf->datalen, nw->num_messages); + struct nl_writer nw; + u_int offset, msglen; - orig = nw->buf; - nb = nl_buf_alloc(orig->datalen + SCRATCH_BUFFER_SIZE, M_NOWAIT); - if (__predict_false(nb == NULL)) - return (false); - nw->buf = nb; - orig_messages = nw->num_messages; - nw->num_messages = 0; + if (__predict_false(!nl_writer_unicast(&nw, + orig->datalen + SCRATCH_BUFFER_SIZE, nlp, false))) + return (NULL); /* Assume correct headers. Buffer IS mutable */ for (offset = 0; @@ -587,22 +580,18 @@ nlmsgs_to_linux(struct nl_writer *nw, struct nlpcb *nlp) struct nlmsghdr *hdr = (struct nlmsghdr *)&orig->data[offset]; msglen = NLMSG_ALIGN(hdr->nlmsg_len); - if (!nlmsg_to_linux(hdr, nlp, nw)) { + if (!nlmsg_to_linux(hdr, nlp, &nw)) { RT_LOG(LOG_DEBUG, "failed to process msg type %d", hdr->nlmsg_type); - nl_buf_free(nb); - nw->buf = orig; - nw->num_messages = orig_messages; - return (false); + nl_buf_free(nw.buf); + return (NULL); } } - MPASS(nw->num_messages == orig_messages); - MPASS(nw->buf == nb); - nl_buf_free(orig); - RT_LOG(LOG_DEBUG3, "%p: out %u bytes", __func__, offset); + RT_LOG(LOG_DEBUG3, "%p: in %u bytes %u messages", __func__, + nw.buf->datalen, nw.num_messages); - return (true); + return (nw.buf); } static struct linux_netlink_provider linux_netlink_v1 = { diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c index 539d153431c4..0e07b0a60ced 100644 --- a/sys/compat/linux/linux_socket.c +++ b/sys/compat/linux/linux_socket.c @@ -2179,6 +2179,7 @@ static int linux_getsockopt_so_peergroups(struct thread *td, struct linux_getsockopt_args *args) { + l_gid_t *out = PTRIN(args->optval); struct xucred xu; socklen_t xulen, len; int error, i; @@ -2197,13 +2198,12 @@ linux_getsockopt_so_peergroups(struct thread *td, return (error); } - /* - * "- 1" to skip the primary group. - */ + /* "- 1" to skip the primary group. */ for (i = 0; i < xu.cr_ngroups - 1; i++) { - error = copyout(xu.cr_groups + i + 1, - (void *)(args->optval + i * sizeof(l_gid_t)), - sizeof(l_gid_t)); + /* Copy to cope with a possible type discrepancy. */ + const l_gid_t g = xu.cr_groups[i + 1]; + + error = copyout(&g, out + i, sizeof(l_gid_t)); if (error != 0) return (error); } diff --git a/sys/compat/linux/linux_uid16.c b/sys/compat/linux/linux_uid16.c index 1d9a19916412..8ac093e004d0 100644 --- a/sys/compat/linux/linux_uid16.c +++ b/sys/compat/linux/linux_uid16.c @@ -85,13 +85,13 @@ linux_lchown16(struct thread *td, struct linux_lchown16_args *args) int linux_setgroups16(struct thread *td, struct linux_setgroups16_args *args) { + const int ngrp = args->gidsetsize; struct ucred *newcred, *oldcred; l_gid16_t *linux_gidset; - int ngrp, error; + int error; struct proc *p; - ngrp = args->gidsetsize; - if (ngrp < 0 || ngrp >= ngroups_max) + if (ngrp < 0 || ngrp > ngroups_max) return (EINVAL); linux_gidset = malloc(ngrp * sizeof(*linux_gidset), M_LINUX, M_WAITOK); error = copyin(args->gidset, linux_gidset, ngrp * sizeof(l_gid16_t)); @@ -100,7 +100,9 @@ linux_setgroups16(struct thread *td, struct linux_setgroups16_args *args) free(linux_gidset, M_LINUX); return (error); } + newcred = crget(); + crextend(newcred, ngrp); p = td->td_proc; PROC_LOCK(p); oldcred = crcopysafe(p, newcred); @@ -133,34 +135,29 @@ out: int linux_getgroups16(struct thread *td, struct linux_getgroups16_args *args) { - struct ucred *cred; + const struct ucred *const cred = td->td_ucred; l_gid16_t *linux_gidset; - gid_t *bsd_gidset; - int bsd_gidsetsz, ngrp, error; + int ngrp, error; - cred = td->td_ucred; - bsd_gidset = cred->cr_groups; - bsd_gidsetsz = cred->cr_ngroups; + ngrp = args->gidsetsize; - if ((ngrp = args->gidsetsize) == 0) { - td->td_retval[0] = bsd_gidsetsz; + if (ngrp == 0) { + td->td_retval[0] = cred->cr_ngroups; return (0); } - - if (ngrp < bsd_gidsetsz) + if (ngrp < cred->cr_ngroups) return (EINVAL); - ngrp = 0; - linux_gidset = malloc(bsd_gidsetsz * sizeof(*linux_gidset), - M_LINUX, M_WAITOK); - while (ngrp < bsd_gidsetsz) { - linux_gidset[ngrp] = bsd_gidset[ngrp]; - ngrp++; - } + ngrp = cred->cr_ngroups; + + linux_gidset = malloc(ngrp * sizeof(*linux_gidset), M_LINUX, M_WAITOK); + for (int i = 0; i < ngrp; ++i) + linux_gidset[i] = cred->cr_groups[i]; error = copyout(linux_gidset, args->gidset, ngrp * sizeof(l_gid16_t)); free(linux_gidset, M_LINUX); - if (error) { + + if (error != 0) { LIN_SDT_PROBE1(uid16, linux_getgroups16, copyout_error, error); return (error); } |