Make struct xinpcb and friends word-size independent.
Replace size_t members with ksize_t (uint64_t) and pointer members (never used as pointers in userspace, but instead as unique idenitifiers) with kvaddr_t (uint64_t). This makes the structs identical between 32-bit and 64-bit ABIs. On 64-bit bit systems, the ABI is maintained. On 32-bit systems, this is an ABI breaking change. The ABI of most of these structs was previously broken in r315662. This also imposes a small API change on userspace consumers who must handle kernel pointers becoming virtual addresses. PR: 228301 (exp-run by antoine) Reviewed by: jtl, kib, rwatson (various versions) Sponsored by: DARPA, AFRL Differential Revision: https://reviews.freebsd.org/D15386
This commit is contained in:
parent
38475506db
commit
6615ed4c61
8
UPDATING
8
UPDATING
@ -31,6 +31,14 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 12.x IS SLOW:
|
||||
disable the most expensive debugging functionality run
|
||||
"ln -s 'abort:false,junk:false' /etc/malloc.conf".)
|
||||
|
||||
20180705:
|
||||
The ABI of syscalls used by management tools like sockstat and
|
||||
netstat has been broken to allow 32-bit binaries to work on
|
||||
64-bit kernels without modification. These programs will need
|
||||
to match the kernel in order to function. External programs may
|
||||
require minor modifications to accommodate a change of type in
|
||||
structures from pointers to 64-bit virtual addresses.
|
||||
|
||||
20180702:
|
||||
On i386 and amd64 atomics are now inlined. Out of tree modules using
|
||||
atomics will need to be rebuilt.
|
||||
|
@ -61,8 +61,6 @@ typedef __ssize_t ssize_t;
|
||||
#define _SSIZE_T_DECLARED
|
||||
#endif
|
||||
|
||||
typedef uint64_t kvaddr_t; /* An address in a target image. */
|
||||
|
||||
struct kvm_nlist {
|
||||
const char *n_name;
|
||||
unsigned char n_type;
|
||||
|
@ -3362,10 +3362,10 @@ sysctl_kern_file(SYSCTL_HANDLER_ARGS)
|
||||
if ((fp = fdp->fd_ofiles[n].fde_file) == NULL)
|
||||
continue;
|
||||
xf.xf_fd = n;
|
||||
xf.xf_file = fp;
|
||||
xf.xf_data = fp->f_data;
|
||||
xf.xf_vnode = fp->f_vnode;
|
||||
xf.xf_type = fp->f_type;
|
||||
xf.xf_file = (kvaddr_t)fp;
|
||||
xf.xf_data = (kvaddr_t)fp->f_data;
|
||||
xf.xf_vnode = (kvaddr_t)fp->f_vnode;
|
||||
xf.xf_type = (kvaddr_t)fp->f_type;
|
||||
xf.xf_count = fp->f_count;
|
||||
xf.xf_msgcount = 0;
|
||||
xf.xf_offset = foffset_get(fp);
|
||||
|
@ -3985,12 +3985,12 @@ sotoxsocket(struct socket *so, struct xsocket *xso)
|
||||
{
|
||||
|
||||
xso->xso_len = sizeof *xso;
|
||||
xso->xso_so = so;
|
||||
xso->xso_so = (kvaddr_t)so;
|
||||
xso->so_type = so->so_type;
|
||||
xso->so_options = so->so_options;
|
||||
xso->so_linger = so->so_linger;
|
||||
xso->so_state = so->so_state;
|
||||
xso->so_pcb = so->so_pcb;
|
||||
xso->so_pcb = (kvaddr_t)so->so_pcb;
|
||||
xso->xso_protocol = so->so_proto->pr_protocol;
|
||||
xso->xso_family = so->so_proto->pr_domain->dom_family;
|
||||
xso->so_timeo = so->so_timeo;
|
||||
|
@ -1853,7 +1853,7 @@ unp_pcblist(SYSCTL_HANDLER_ARGS)
|
||||
|
||||
if (freeunp == 0 && unp->unp_gencnt <= gencnt) {
|
||||
xu->xu_len = sizeof *xu;
|
||||
xu->xu_unpp = unp;
|
||||
xu->xu_unpp = (kvaddr_t)unp;
|
||||
/*
|
||||
* XXX - need more locking here to protect against
|
||||
* connect/disconnect races for SMP.
|
||||
@ -1870,10 +1870,10 @@ unp_pcblist(SYSCTL_HANDLER_ARGS)
|
||||
unp->unp_conn->unp_addr->sun_len);
|
||||
else
|
||||
bzero(&xu->xu_caddr, sizeof(xu->xu_caddr));
|
||||
xu->unp_vnode = unp->unp_vnode;
|
||||
xu->unp_conn = unp->unp_conn;
|
||||
xu->xu_firstref = LIST_FIRST(&unp->unp_refs);
|
||||
xu->xu_nextref = LIST_NEXT(unp, unp_reflink);
|
||||
xu->unp_vnode = (kvaddr_t)unp->unp_vnode;
|
||||
xu->unp_conn = (kvaddr_t)unp->unp_conn;
|
||||
xu->xu_firstref = (kvaddr_t)LIST_FIRST(&unp->unp_refs);
|
||||
xu->xu_nextref = (kvaddr_t)LIST_NEXT(unp, unp_reflink);
|
||||
xu->unp_gencnt = unp->unp_gencnt;
|
||||
sotoxsocket(unp->unp_socket, &xu->xu_socket);
|
||||
UNP_PCB_UNLOCK(unp);
|
||||
|
@ -2906,7 +2906,7 @@ in_pcbtoxinpcb(const struct inpcb *inp, struct xinpcb *xi)
|
||||
bzero(&xi->xi_socket, sizeof(struct xsocket));
|
||||
bcopy(&inp->inp_inc, &xi->inp_inc, sizeof(struct in_conninfo));
|
||||
xi->inp_gencnt = inp->inp_gencnt;
|
||||
xi->inp_ppcb = inp->inp_ppcb;
|
||||
xi->inp_ppcb = (kvaddr_t)inp->inp_ppcb;
|
||||
xi->inp_flow = inp->inp_flow;
|
||||
xi->inp_flowid = inp->inp_flowid;
|
||||
xi->inp_flowtype = inp->inp_flowtype;
|
||||
|
@ -366,12 +366,12 @@ struct inpcb {
|
||||
*/
|
||||
#ifdef _SYS_SOCKETVAR_H_
|
||||
struct xinpcb {
|
||||
size_t xi_len; /* length of this structure */
|
||||
ksize_t xi_len; /* length of this structure */
|
||||
struct xsocket xi_socket; /* (s,p) */
|
||||
struct in_conninfo inp_inc; /* (s,p) */
|
||||
uint64_t inp_gencnt; /* (s,p) */
|
||||
union {
|
||||
void *inp_ppcb; /* (s) netstat(1) */
|
||||
kvaddr_t inp_ppcb; /* (s) netstat(1) */
|
||||
int64_t ph_ppcb;
|
||||
};
|
||||
int64_t inp_spare64[4];
|
||||
@ -394,10 +394,12 @@ struct xinpcb {
|
||||
} __aligned(8);
|
||||
|
||||
struct xinpgen {
|
||||
size_t xig_len; /* length of this structure */
|
||||
ksize_t xig_len; /* length of this structure */
|
||||
u_int xig_count; /* number of PCBs at this time */
|
||||
uint32_t _xig_spare32;
|
||||
inp_gen_t xig_gen; /* generation count at this time */
|
||||
so_gen_t xig_sogen; /* socket generation count this time */
|
||||
uint64_t _xig_spare64[4];
|
||||
} __aligned(8);
|
||||
#ifdef _KERNEL
|
||||
void in_pcbtoxinpcb(const struct inpcb *, struct xinpcb *);
|
||||
|
@ -409,7 +409,7 @@ sctp_sysctl_handle_assoclist(SYSCTL_HANDLER_ARGS)
|
||||
xinpcb.total_recvs = inp->total_recvs;
|
||||
xinpcb.total_nospaces = inp->total_nospaces;
|
||||
xinpcb.fragmentation_point = inp->sctp_frag_point;
|
||||
xinpcb.socket = inp->sctp_socket;
|
||||
xinpcb.socket = (kvaddr_t)inp->sctp_socket;
|
||||
so = inp->sctp_socket;
|
||||
if ((so == NULL) ||
|
||||
(!SCTP_IS_LISTENING(inp)) ||
|
||||
|
@ -1175,14 +1175,11 @@ struct xsctp_inpcb {
|
||||
uint16_t local_port;
|
||||
uint16_t qlen_old;
|
||||
uint16_t maxqlen_old;
|
||||
void *socket;
|
||||
uint16_t __spare16;
|
||||
kvaddr_t socket;
|
||||
uint32_t qlen;
|
||||
uint32_t maxqlen;
|
||||
#if defined(__LP64__)
|
||||
uint32_t extra_padding[27]; /* future */
|
||||
#else
|
||||
uint32_t extra_padding[28]; /* future */
|
||||
#endif
|
||||
uint32_t extra_padding[26]; /* future */
|
||||
};
|
||||
|
||||
struct xsctp_tcb {
|
||||
|
@ -677,7 +677,7 @@ void hhook_run_tcp_est_out(struct tcpcb *tp,
|
||||
*/
|
||||
#if defined(_NETINET_IN_PCB_H_) && defined(_SYS_SOCKETVAR_H_)
|
||||
struct xtcpcb {
|
||||
size_t xt_len; /* length of this structure */
|
||||
ksize_t xt_len; /* length of this structure */
|
||||
struct xinpcb xt_inp;
|
||||
char xt_stack[TCP_FUNCTION_NAME_LEN_MAX]; /* (s) */
|
||||
char xt_logid[TCP_LOG_ID_LEN]; /* (s) */
|
||||
|
@ -209,18 +209,23 @@ struct file {
|
||||
* Userland version of struct file, for sysctl
|
||||
*/
|
||||
struct xfile {
|
||||
size_t xf_size; /* size of struct xfile */
|
||||
ksize_t xf_size; /* size of struct xfile */
|
||||
pid_t xf_pid; /* owning process */
|
||||
uid_t xf_uid; /* effective uid of owning process */
|
||||
int xf_fd; /* descriptor number */
|
||||
void *xf_file; /* address of struct file */
|
||||
int _xf_int_pad1;
|
||||
kvaddr_t xf_file; /* address of struct file */
|
||||
short xf_type; /* descriptor type */
|
||||
short _xf_short_pad1;
|
||||
int xf_count; /* reference count */
|
||||
int xf_msgcount; /* references from message queue */
|
||||
int _xf_int_pad2;
|
||||
off_t xf_offset; /* file offset */
|
||||
void *xf_data; /* file descriptor specific data */
|
||||
void *xf_vnode; /* vnode pointer */
|
||||
kvaddr_t xf_data; /* file descriptor specific data */
|
||||
kvaddr_t xf_vnode; /* vnode pointer */
|
||||
u_int xf_flag; /* flags (see fcntl.h) */
|
||||
int _xf_int_pad3;
|
||||
int64_t _xf_int64_pad[6];
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
@ -60,7 +60,7 @@
|
||||
* in the range 5 to 9.
|
||||
*/
|
||||
#undef __FreeBSD_version
|
||||
#define __FreeBSD_version 1200071 /* Master, propagated to newvers */
|
||||
#define __FreeBSD_version 1200072 /* Master, propagated to newvers */
|
||||
|
||||
/*
|
||||
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
|
||||
|
@ -474,13 +474,13 @@ int accept_filt_generic_mod_event(module_t mod, int event, void *data);
|
||||
* Structure to export socket from kernel to utilities, via sysctl(3).
|
||||
*/
|
||||
struct xsocket {
|
||||
size_t xso_len; /* length of this structure */
|
||||
ksize_t xso_len; /* length of this structure */
|
||||
union {
|
||||
void *xso_so; /* kernel address of struct socket */
|
||||
kvaddr_t xso_so; /* kernel address of struct socket */
|
||||
int64_t ph_so;
|
||||
};
|
||||
union {
|
||||
void *so_pcb; /* kernel address of struct inpcb */
|
||||
kvaddr_t so_pcb; /* kernel address of struct inpcb */
|
||||
int64_t ph_pcb;
|
||||
};
|
||||
uint64_t so_oobmark;
|
||||
|
@ -251,6 +251,15 @@ struct cap_rights;
|
||||
typedef struct cap_rights cap_rights_t;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Types suitable for exporting size and pointers (as virtual addresses)
|
||||
* from the kernel independent of native word size. These should be
|
||||
* used in place of size_t and (u)intptr_t in structs which contain such
|
||||
* types that are shared with userspace.
|
||||
*/
|
||||
typedef __uint64_t kvaddr_t;
|
||||
typedef __uint64_t ksize_t;
|
||||
|
||||
typedef __vm_offset_t vm_offset_t;
|
||||
typedef __int64_t vm_ooffset_t;
|
||||
typedef __vm_paddr_t vm_paddr_t;
|
||||
|
@ -138,12 +138,12 @@ struct unpcb {
|
||||
*/
|
||||
#ifdef _SYS_SOCKETVAR_H_
|
||||
struct xunpcb {
|
||||
size_t xu_len; /* length of this structure */
|
||||
void *xu_unpp; /* to help netstat, fstat */
|
||||
void *unp_vnode; /* (s) */
|
||||
void *unp_conn; /* (s) */
|
||||
void *xu_firstref; /* (s) */
|
||||
void *xu_nextref; /* (s) */
|
||||
ksize_t xu_len; /* length of this structure */
|
||||
kvaddr_t xu_unpp; /* to help netstat, fstat */
|
||||
kvaddr_t unp_vnode; /* (s) */
|
||||
kvaddr_t unp_conn; /* (s) */
|
||||
kvaddr_t xu_firstref; /* (s) */
|
||||
kvaddr_t xu_nextref; /* (s) */
|
||||
unp_gen_t unp_gencnt; /* (s) */
|
||||
int64_t xu_spare64[8];
|
||||
int32_t xu_spare32[8];
|
||||
@ -159,7 +159,7 @@ struct xunpcb {
|
||||
} __aligned(8);
|
||||
|
||||
struct xunpgen {
|
||||
size_t xug_len;
|
||||
ksize_t xug_len;
|
||||
u_int xug_count;
|
||||
unp_gen_t xug_gen;
|
||||
so_gen_t xug_sogen;
|
||||
|
@ -159,12 +159,12 @@ sotoxsocket(struct socket *so, struct xsocket *xso)
|
||||
|
||||
bzero(xso, sizeof *xso);
|
||||
xso->xso_len = sizeof *xso;
|
||||
xso->xso_so = so;
|
||||
xso->xso_so = (kvaddr_t)so;
|
||||
xso->so_type = so->so_type;
|
||||
xso->so_options = so->so_options;
|
||||
xso->so_linger = so->so_linger;
|
||||
xso->so_state = so->so_state;
|
||||
xso->so_pcb = so->so_pcb;
|
||||
xso->so_pcb = (kvaddr_t)so->so_pcb;
|
||||
if (kread((uintptr_t)so->so_proto, &proto, sizeof(proto)) != 0)
|
||||
return (-1);
|
||||
xso->xso_protocol = proto.pr_protocol;
|
||||
|
@ -153,7 +153,7 @@ pcblist_kvm(u_long count_off, u_long gencnt_off, u_long head_off, char **bufp)
|
||||
xu.xu_len = sizeof xu;
|
||||
KREAD(head_off, &head, sizeof(head));
|
||||
LIST_FOREACH(unp, &head, unp_link) {
|
||||
xu.xu_unpp = unp;
|
||||
xu.xu_unpp = (kvaddr_t)unp;
|
||||
KREAD(unp, &unp0, sizeof (*unp));
|
||||
unp = &unp0;
|
||||
|
||||
|
@ -108,8 +108,8 @@ struct addr {
|
||||
};
|
||||
|
||||
struct sock {
|
||||
void *socket;
|
||||
void *pcb;
|
||||
kvaddr_t socket;
|
||||
kvaddr_t pcb;
|
||||
int shown;
|
||||
int vflag;
|
||||
int family;
|
||||
@ -789,8 +789,8 @@ gather_unix(int proto)
|
||||
warnx("struct xunpcb size mismatch");
|
||||
goto out;
|
||||
}
|
||||
if ((xup->unp_conn == NULL && !opt_l) ||
|
||||
(xup->unp_conn != NULL && !opt_c))
|
||||
if ((xup->unp_conn == 0 && !opt_l) ||
|
||||
(xup->unp_conn != 0 && !opt_c))
|
||||
continue;
|
||||
if ((sock = calloc(1, sizeof(*sock))) == NULL)
|
||||
err(1, "malloc()");
|
||||
@ -806,8 +806,8 @@ gather_unix(int proto)
|
||||
if (xup->xu_addr.sun_family == AF_UNIX)
|
||||
laddr->address =
|
||||
*(struct sockaddr_storage *)(void *)&xup->xu_addr;
|
||||
else if (xup->unp_conn != NULL)
|
||||
*(void **)&(faddr->address) = xup->unp_conn;
|
||||
else if (xup->unp_conn != 0)
|
||||
*(kvaddr_t*)&(faddr->address) = xup->unp_conn;
|
||||
laddr->next = NULL;
|
||||
faddr->next = NULL;
|
||||
sock->laddr = laddr;
|
||||
@ -1008,7 +1008,7 @@ sctp_path_state(int state)
|
||||
static void
|
||||
displaysock(struct sock *s, int pos)
|
||||
{
|
||||
void *p;
|
||||
kvaddr_t p;
|
||||
int hash, first, offset;
|
||||
struct addr *laddr, *faddr;
|
||||
struct sock *s_tmp;
|
||||
@ -1054,8 +1054,8 @@ displaysock(struct sock *s, int pos)
|
||||
break;
|
||||
}
|
||||
/* client */
|
||||
p = *(void **)&(faddr->address);
|
||||
if (p == NULL) {
|
||||
p = *(kvaddr_t*)&(faddr->address);
|
||||
if (p == 0) {
|
||||
pos += xprintf("(not connected)");
|
||||
offset += opt_w ? 92 : 44;
|
||||
break;
|
||||
@ -1174,13 +1174,13 @@ display(void)
|
||||
}
|
||||
setpassent(1);
|
||||
for (xf = xfiles, n = 0; n < nxfiles; ++n, ++xf) {
|
||||
if (xf->xf_data == NULL)
|
||||
if (xf->xf_data == 0)
|
||||
continue;
|
||||
if (opt_j >= 0 && opt_j != getprocjid(xf->xf_pid))
|
||||
continue;
|
||||
hash = (int)((uintptr_t)xf->xf_data % HASHSIZE);
|
||||
for (s = sockhash[hash]; s != NULL; s = s->next) {
|
||||
if ((void *)s->socket != xf->xf_data)
|
||||
if (s->socket != xf->xf_data)
|
||||
continue;
|
||||
if (!check_ports(s))
|
||||
continue;
|
||||
|
Loading…
Reference in New Issue
Block a user