uipc: rework recvfrom, getsockname, getpeername

Stop using <foo>_args structs as part of internal kernel APIs.  Add
a kern_recvfrom and adjust getsockname and getpeername's equivalent
functions to take individual arguments rather than a uap pointer.

Adopt a convention from CheriBSD that a function interacting with
userspace pointers and sitting between the sys_<foo> syscall and
kern_<foo> implementation is named user_<foo>.

Reviewed by:	kib, imp
This commit is contained in:
Brooks Davis 2021-11-29 22:02:59 +00:00
parent 3660e76a22
commit 28f0471884

View File

@ -78,10 +78,6 @@ static int recvit(struct thread *td, int s, struct msghdr *mp, void *namelenp);
static int accept1(struct thread *td, int s, struct sockaddr *uname,
socklen_t *anamelen, int flags);
static int getsockname1(struct thread *td, struct getsockname_args *uap,
int compat);
static int getpeername1(struct thread *td, struct getpeername_args *uap,
int compat);
static int sockargs(struct mbuf **, char *, socklen_t, int);
/*
@ -1069,40 +1065,48 @@ recvit(struct thread *td, int s, struct msghdr *mp, void *namelenp)
return (error);
}
int
sys_recvfrom(struct thread *td, struct recvfrom_args *uap)
static int
kern_recvfrom(struct thread *td, int s, void *buf, size_t len, int flags,
struct sockaddr *from, socklen_t *fromlenaddr)
{
struct msghdr msg;
struct iovec aiov;
int error;
if (uap->fromlenaddr) {
error = copyin(uap->fromlenaddr,
&msg.msg_namelen, sizeof (msg.msg_namelen));
if (fromlenaddr != NULL) {
error = copyin(fromlenaddr, &msg.msg_namelen,
sizeof (msg.msg_namelen));
if (error != 0)
goto done2;
} else {
msg.msg_namelen = 0;
}
msg.msg_name = uap->from;
msg.msg_name = from;
msg.msg_iov = &aiov;
msg.msg_iovlen = 1;
aiov.iov_base = uap->buf;
aiov.iov_len = uap->len;
aiov.iov_base = buf;
aiov.iov_len = len;
msg.msg_control = 0;
msg.msg_flags = uap->flags;
error = recvit(td, uap->s, &msg, uap->fromlenaddr);
msg.msg_flags = flags;
error = recvit(td, s, &msg, fromlenaddr);
done2:
return (error);
}
int
sys_recvfrom(struct thread *td, struct recvfrom_args *uap)
{
return (kern_recvfrom(td, uap->s, uap->buf, uap->len,
uap->flags, uap->from, uap->fromlenaddr));
}
#ifdef COMPAT_OLDSOCK
int
orecvfrom(struct thread *td, struct recvfrom_args *uap)
{
uap->flags |= MSG_COMPAT;
return (sys_recvfrom(td, uap));
return (kern_recvfrom(td, uap->s, uap->buf, uap->len,
uap->flags | MSG_COMPAT, uap->from, uap->fromlenaddr));
}
#endif
@ -1331,21 +1335,19 @@ kern_getsockopt(struct thread *td, int s, int level, int name, void *val,
return (error);
}
/*
* getsockname1() - Get socket name.
*/
static int
getsockname1(struct thread *td, struct getsockname_args *uap, int compat)
user_getsockname(struct thread *td, int fdes, struct sockaddr *asa,
socklen_t *alen, bool compat)
{
struct sockaddr *sa;
socklen_t len;
int error;
error = copyin(uap->alen, &len, sizeof(len));
error = copyin(alen, &len, sizeof(len));
if (error != 0)
return (error);
error = kern_getsockname(td, uap->fdes, &sa, &len);
error = kern_getsockname(td, fdes, &sa, &len);
if (error != 0)
return (error);
@ -1354,11 +1356,11 @@ getsockname1(struct thread *td, struct getsockname_args *uap, int compat)
if (compat && SV_PROC_FLAG(td->td_proc, SV_AOUT))
((struct osockaddr *)sa)->sa_family = sa->sa_family;
#endif
error = copyout(sa, uap->asa, (u_int)len);
error = copyout(sa, asa, len);
}
free(sa, M_SONAME);
if (error == 0)
error = copyout(&len, uap->alen, sizeof(len));
error = copyout(&len, alen, sizeof(len));
return (error);
}
@ -1404,34 +1406,30 @@ bad:
int
sys_getsockname(struct thread *td, struct getsockname_args *uap)
{
return (getsockname1(td, uap, 0));
return (user_getsockname(td, uap->fdes, uap->asa, uap->alen, false));
}
#ifdef COMPAT_OLDSOCK
int
ogetsockname(struct thread *td, struct getsockname_args *uap)
{
return (getsockname1(td, uap, 1));
return (user_getsockname(td, uap->fdes, uap->asa, uap->alen, true));
}
#endif /* COMPAT_OLDSOCK */
/*
* getpeername1() - Get name of peer for connected socket.
*/
static int
getpeername1(struct thread *td, struct getpeername_args *uap, int compat)
user_getpeername(struct thread *td, int fdes, struct sockaddr *asa,
socklen_t *alen, int compat)
{
struct sockaddr *sa;
socklen_t len;
int error;
error = copyin(uap->alen, &len, sizeof (len));
error = copyin(alen, &len, sizeof (len));
if (error != 0)
return (error);
error = kern_getpeername(td, uap->fdes, &sa, &len);
error = kern_getpeername(td, fdes, &sa, &len);
if (error != 0)
return (error);
@ -1440,11 +1438,11 @@ getpeername1(struct thread *td, struct getpeername_args *uap, int compat)
if (compat && SV_PROC_FLAG(td->td_proc, SV_AOUT))
((struct osockaddr *)sa)->sa_family = sa->sa_family;
#endif
error = copyout(sa, uap->asa, (u_int)len);
error = copyout(sa, asa, len);
}
free(sa, M_SONAME);
if (error == 0)
error = copyout(&len, uap->alen, sizeof(len));
error = copyout(&len, alen, sizeof(len));
return (error);
}
@ -1495,17 +1493,14 @@ done:
int
sys_getpeername(struct thread *td, struct getpeername_args *uap)
{
return (getpeername1(td, uap, 0));
return (user_getpeername(td, uap->fdes, uap->asa, uap->alen, 0));
}
#ifdef COMPAT_OLDSOCK
int
ogetpeername(struct thread *td, struct ogetpeername_args *uap)
{
/* XXX uap should have type `getpeername_args *' to begin with. */
return (getpeername1(td, (struct getpeername_args *)uap, 1));
return (user_getpeername(td, uap->fdes, uap->asa, uap->alen, 1));
}
#endif /* COMPAT_OLDSOCK */