aboutsummaryrefslogtreecommitdiff
path: root/sys/compat/linux
diff options
context:
space:
mode:
Diffstat (limited to 'sys/compat/linux')
-rw-r--r--sys/compat/linux/linux_misc.c41
-rw-r--r--sys/compat/linux/linux_netlink.c37
-rw-r--r--sys/compat/linux/linux_socket.c12
-rw-r--r--sys/compat/linux/linux_uid16.c39
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);
}