linux-user: Add most IFTUN ioctls
The three options handling `struct sock_fprog` (TUNATTACHFILTER, TUNDETACHFILTER, and TUNGETFILTER) are not implemented. Linux kernel keeps a user space pointer in them which we cannot correctly handle. Signed-off-by: Josh Kunz <jkz@google.com> Signed-off-by: Shu-Chun Weng <scw@google.com> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <20200929014801.655524-1-scw@google.com> [lv: use 0 size in unlock_user()] Signed-off-by: Laurent Vivier <laurent@vivier.eu>
This commit is contained in:
parent
8494645797
commit
6addf06a3c
@ -720,3 +720,49 @@
|
||||
IOCTL(KCOV_DISABLE, 0, TYPE_NULL)
|
||||
IOCTL(KCOV_INIT_TRACE, IOC_R, TYPE_ULONG)
|
||||
#endif
|
||||
|
||||
IOCTL(TUNSETDEBUG, IOC_W, TYPE_INT)
|
||||
IOCTL(TUNSETIFF, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))
|
||||
IOCTL(TUNSETPERSIST, IOC_W, TYPE_INT)
|
||||
IOCTL(TUNSETOWNER, IOC_W, TYPE_INT)
|
||||
IOCTL(TUNSETLINK, IOC_W, TYPE_INT)
|
||||
IOCTL(TUNSETGROUP, IOC_W, TYPE_INT)
|
||||
IOCTL(TUNGETFEATURES, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(TUNSETOFFLOAD, IOC_W, TYPE_LONG)
|
||||
IOCTL_SPECIAL(TUNSETTXFILTER, IOC_W, do_ioctl_TUNSETTXFILTER,
|
||||
/*
|
||||
* We can't represent `struct tun_filter` in thunk so leaving
|
||||
* it uninterpreted. do_ioctl_TUNSETTXFILTER will do the
|
||||
* conversion.
|
||||
*/
|
||||
TYPE_PTRVOID)
|
||||
IOCTL(TUNGETIFF, IOC_R, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))
|
||||
IOCTL(TUNGETSNDBUF, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(TUNSETSNDBUF, IOC_W, MK_PTR(TYPE_INT))
|
||||
/*
|
||||
* TUNATTACHFILTER and TUNDETACHFILTER are not supported. Linux kernel keeps a
|
||||
* user pointer in TUNATTACHFILTER, which we are not able to correctly handle.
|
||||
*/
|
||||
IOCTL(TUNGETVNETHDRSZ, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(TUNSETVNETHDRSZ, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(TUNSETQUEUE, IOC_W, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))
|
||||
IOCTL(TUNSETIFINDEX , IOC_W, MK_PTR(TYPE_INT))
|
||||
/* TUNGETFILTER is not supported: see TUNATTACHFILTER. */
|
||||
IOCTL(TUNSETVNETLE, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(TUNGETVNETLE, IOC_R, MK_PTR(TYPE_INT))
|
||||
#ifdef TUNSETVNETBE
|
||||
IOCTL(TUNSETVNETBE, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(TUNGETVNETBE, IOC_R, MK_PTR(TYPE_INT))
|
||||
#endif
|
||||
#ifdef TUNSETSTEERINGEBPF
|
||||
IOCTL(TUNSETSTEERINGEBPF, IOC_W, MK_PTR(TYPE_INT))
|
||||
#endif
|
||||
#ifdef TUNSETFILTEREBPF
|
||||
IOCTL(TUNSETFILTEREBPF, IOC_W, MK_PTR(TYPE_INT))
|
||||
#endif
|
||||
#ifdef TUNSETCARRIER
|
||||
IOCTL(TUNSETCARRIER, IOC_W, MK_PTR(TYPE_INT))
|
||||
#endif
|
||||
#ifdef TUNGETDEVNETNS
|
||||
IOCTL(TUNGETDEVNETNS, IOC_R, TYPE_NULL)
|
||||
#endif
|
||||
|
@ -56,6 +56,7 @@
|
||||
#include <linux/wireless.h>
|
||||
#include <linux/icmp.h>
|
||||
#include <linux/icmpv6.h>
|
||||
#include <linux/if_tun.h>
|
||||
#include <linux/errqueue.h>
|
||||
#include <linux/random.h>
|
||||
#ifdef CONFIG_TIMERFD
|
||||
@ -5709,6 +5710,42 @@ static abi_long do_ioctl_drm_i915(const IOCTLEntry *ie, uint8_t *buf_temp,
|
||||
|
||||
#endif
|
||||
|
||||
static abi_long do_ioctl_TUNSETTXFILTER(const IOCTLEntry *ie, uint8_t *buf_temp,
|
||||
int fd, int cmd, abi_long arg)
|
||||
{
|
||||
struct tun_filter *filter = (struct tun_filter *)buf_temp;
|
||||
struct tun_filter *target_filter;
|
||||
char *target_addr;
|
||||
|
||||
assert(ie->access == IOC_W);
|
||||
|
||||
target_filter = lock_user(VERIFY_READ, arg, sizeof(*target_filter), 1);
|
||||
if (!target_filter) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
filter->flags = tswap16(target_filter->flags);
|
||||
filter->count = tswap16(target_filter->count);
|
||||
unlock_user(target_filter, arg, 0);
|
||||
|
||||
if (filter->count) {
|
||||
if (offsetof(struct tun_filter, addr) + filter->count * ETH_ALEN >
|
||||
MAX_STRUCT_SIZE) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
|
||||
target_addr = lock_user(VERIFY_READ,
|
||||
arg + offsetof(struct tun_filter, addr),
|
||||
filter->count * ETH_ALEN, 1);
|
||||
if (!target_addr) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
memcpy(filter->addr, target_addr, filter->count * ETH_ALEN);
|
||||
unlock_user(target_addr, arg + offsetof(struct tun_filter, addr), 0);
|
||||
}
|
||||
|
||||
return get_errno(safe_ioctl(fd, ie->host_cmd, filter));
|
||||
}
|
||||
|
||||
IOCTLEntry ioctl_entries[] = {
|
||||
#define IOCTL(cmd, access, ...) \
|
||||
{ TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
|
||||
|
@ -929,6 +929,38 @@ struct target_rtc_pll_info {
|
||||
|
||||
#define TARGET_SIOCGIWNAME 0x8B01 /* get name == wireless protocol */
|
||||
|
||||
/* From <linux/if_tun.h> */
|
||||
|
||||
#define TARGET_TUNSETDEBUG TARGET_IOW('T', 201, int)
|
||||
#define TARGET_TUNSETIFF TARGET_IOW('T', 202, int)
|
||||
#define TARGET_TUNSETPERSIST TARGET_IOW('T', 203, int)
|
||||
#define TARGET_TUNSETOWNER TARGET_IOW('T', 204, int)
|
||||
#define TARGET_TUNSETLINK TARGET_IOW('T', 205, int)
|
||||
#define TARGET_TUNSETGROUP TARGET_IOW('T', 206, int)
|
||||
#define TARGET_TUNGETFEATURES TARGET_IOR('T', 207, unsigned int)
|
||||
#define TARGET_TUNSETOFFLOAD TARGET_IOW('T', 208, unsigned int)
|
||||
#define TARGET_TUNSETTXFILTER TARGET_IOW('T', 209, unsigned int)
|
||||
#define TARGET_TUNGETIFF TARGET_IOR('T', 210, unsigned int)
|
||||
#define TARGET_TUNGETSNDBUF TARGET_IOR('T', 211, int)
|
||||
#define TARGET_TUNSETSNDBUF TARGET_IOW('T', 212, int)
|
||||
/*
|
||||
* TUNATTACHFILTER and TUNDETACHFILTER are not supported. Linux kernel keeps a
|
||||
* user pointer in TUNATTACHFILTER, which we are not able to correctly handle.
|
||||
*/
|
||||
#define TARGET_TUNGETVNETHDRSZ TARGET_IOR('T', 215, int)
|
||||
#define TARGET_TUNSETVNETHDRSZ TARGET_IOW('T', 216, int)
|
||||
#define TARGET_TUNSETQUEUE TARGET_IOW('T', 217, int)
|
||||
#define TARGET_TUNSETIFINDEX TARGET_IOW('T', 218, unsigned int)
|
||||
/* TUNGETFILTER is not supported: see TUNATTACHFILTER. */
|
||||
#define TARGET_TUNSETVNETLE TARGET_IOW('T', 220, int)
|
||||
#define TARGET_TUNGETVNETLE TARGET_IOR('T', 221, int)
|
||||
#define TARGET_TUNSETVNETBE TARGET_IOW('T', 222, int)
|
||||
#define TARGET_TUNGETVNETBE TARGET_IOR('T', 223, int)
|
||||
#define TARGET_TUNSETSTEERINGEBPF TARGET_IOR('T', 224, int)
|
||||
#define TARGET_TUNSETFILTEREBPF TARGET_IOR('T', 225, int)
|
||||
#define TARGET_TUNSETCARRIER TARGET_IOW('T', 226, int)
|
||||
#define TARGET_TUNGETDEVNETNS TARGET_IO('T', 227)
|
||||
|
||||
/* From <linux/random.h> */
|
||||
|
||||
#define TARGET_RNDGETENTCNT TARGET_IOR('R', 0x00, int)
|
||||
|
Loading…
Reference in New Issue
Block a user