mirror of https://gitee.com/openkylin/linux.git
s390/qeth: sanitize ARP requests
The ARP_{ADD,REMOVE}_ENTRY cmd structs contain reserved fields. Introduce a common helper that doesn't raw-copy the user-provided data into the cmd, but only sets those fields that are strictly needed for the command. This also sets the correct command length for ARP_REMOVE_ENTRY. Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
9fae5c3b60
commit
125d7d3011
|
@ -1046,11 +1046,6 @@ int qeth_configure_cq(struct qeth_card *, enum qeth_cq);
|
|||
int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action);
|
||||
void qeth_trace_features(struct qeth_card *);
|
||||
void qeth_close_dev(struct qeth_card *);
|
||||
int qeth_send_setassparms(struct qeth_card *, struct qeth_cmd_buffer *, __u16,
|
||||
long,
|
||||
int (*reply_cb)(struct qeth_card *,
|
||||
struct qeth_reply *, unsigned long),
|
||||
void *);
|
||||
int qeth_setassparms_cb(struct qeth_card *, struct qeth_reply *, unsigned long);
|
||||
struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *,
|
||||
enum qeth_ipa_funcs,
|
||||
|
|
|
@ -5477,11 +5477,12 @@ struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *card,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_get_setassparms_cmd);
|
||||
|
||||
int qeth_send_setassparms(struct qeth_card *card,
|
||||
struct qeth_cmd_buffer *iob, __u16 len, long data,
|
||||
int (*reply_cb)(struct qeth_card *,
|
||||
struct qeth_reply *, unsigned long),
|
||||
void *reply_param)
|
||||
static int qeth_send_setassparms(struct qeth_card *card,
|
||||
struct qeth_cmd_buffer *iob, u16 len,
|
||||
long data, int (*reply_cb)(struct qeth_card *,
|
||||
struct qeth_reply *,
|
||||
unsigned long),
|
||||
void *reply_param)
|
||||
{
|
||||
int rc;
|
||||
struct qeth_ipa_cmd *cmd;
|
||||
|
@ -5497,7 +5498,6 @@ int qeth_send_setassparms(struct qeth_card *card,
|
|||
rc = qeth_send_ipa_cmd(card, iob, reply_cb, reply_param);
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_send_setassparms);
|
||||
|
||||
int qeth_send_simple_setassparms_prot(struct qeth_card *card,
|
||||
enum qeth_ipa_funcs ipa_func,
|
||||
|
|
|
@ -436,7 +436,7 @@ struct qeth_ipacmd_setassparms {
|
|||
__u32 flags_32bit;
|
||||
struct qeth_ipa_caps caps;
|
||||
struct qeth_checksum_cmd chksum;
|
||||
struct qeth_arp_cache_entry add_arp_entry;
|
||||
struct qeth_arp_cache_entry arp_entry;
|
||||
struct qeth_arp_query_data query_arp;
|
||||
struct qeth_tso_start_data tso;
|
||||
__u8 ip[16];
|
||||
|
|
|
@ -1777,13 +1777,18 @@ static int qeth_l3_arp_query(struct qeth_card *card, char __user *udata)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int qeth_l3_arp_add_entry(struct qeth_card *card,
|
||||
struct qeth_arp_cache_entry *entry)
|
||||
static int qeth_l3_arp_modify_entry(struct qeth_card *card,
|
||||
struct qeth_arp_cache_entry *entry,
|
||||
enum qeth_arp_process_subcmds arp_cmd)
|
||||
{
|
||||
struct qeth_arp_cache_entry *cmd_entry;
|
||||
struct qeth_cmd_buffer *iob;
|
||||
int rc;
|
||||
|
||||
QETH_CARD_TEXT(card, 3, "arpadent");
|
||||
if (arp_cmd == IPA_CMD_ASS_ARP_ADD_ENTRY)
|
||||
QETH_CARD_TEXT(card, 3, "arpadd");
|
||||
else
|
||||
QETH_CARD_TEXT(card, 3, "arpdel");
|
||||
|
||||
/*
|
||||
* currently GuestLAN only supports the ARP assist function
|
||||
|
@ -1796,54 +1801,19 @@ static int qeth_l3_arp_add_entry(struct qeth_card *card,
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
|
||||
IPA_CMD_ASS_ARP_ADD_ENTRY,
|
||||
sizeof(struct qeth_arp_cache_entry),
|
||||
QETH_PROT_IPV4);
|
||||
iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING, arp_cmd,
|
||||
sizeof(*cmd_entry), QETH_PROT_IPV4);
|
||||
if (!iob)
|
||||
return -ENOMEM;
|
||||
rc = qeth_send_setassparms(card, iob,
|
||||
sizeof(struct qeth_arp_cache_entry),
|
||||
(unsigned long) entry,
|
||||
qeth_setassparms_cb, NULL);
|
||||
|
||||
cmd_entry = &__ipa_cmd(iob)->data.setassparms.data.arp_entry;
|
||||
ether_addr_copy(cmd_entry->macaddr, entry->macaddr);
|
||||
memcpy(cmd_entry->ipaddr, entry->ipaddr, 4);
|
||||
rc = qeth_send_ipa_cmd(card, iob, qeth_setassparms_cb, NULL);
|
||||
if (rc)
|
||||
QETH_DBF_MESSAGE(2, "Could not add ARP entry on device %x: %#x\n",
|
||||
CARD_DEVID(card), rc);
|
||||
return qeth_l3_arp_makerc(rc);
|
||||
}
|
||||
QETH_DBF_MESSAGE(2, "Could not modify (cmd: %#x) ARP entry on device %x: %#x\n",
|
||||
arp_cmd, CARD_DEVID(card), rc);
|
||||
|
||||
static int qeth_l3_arp_remove_entry(struct qeth_card *card,
|
||||
struct qeth_arp_cache_entry *entry)
|
||||
{
|
||||
struct qeth_cmd_buffer *iob;
|
||||
char buf[16] = {0, };
|
||||
int rc;
|
||||
|
||||
QETH_CARD_TEXT(card, 3, "arprment");
|
||||
|
||||
/*
|
||||
* currently GuestLAN only supports the ARP assist function
|
||||
* IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_REMOVE_ENTRY;
|
||||
* thus we say EOPNOTSUPP for this ARP function
|
||||
*/
|
||||
if (card->info.guestlan)
|
||||
return -EOPNOTSUPP;
|
||||
if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
memcpy(buf, entry, 12);
|
||||
iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
|
||||
IPA_CMD_ASS_ARP_REMOVE_ENTRY,
|
||||
12,
|
||||
QETH_PROT_IPV4);
|
||||
if (!iob)
|
||||
return -ENOMEM;
|
||||
rc = qeth_send_setassparms(card, iob,
|
||||
12, (unsigned long)buf,
|
||||
qeth_setassparms_cb, NULL);
|
||||
if (rc)
|
||||
QETH_DBF_MESSAGE(2, "Could not delete ARP entry on device %x: %#x\n",
|
||||
CARD_DEVID(card), rc);
|
||||
return qeth_l3_arp_makerc(rc);
|
||||
}
|
||||
|
||||
|
@ -1875,6 +1845,7 @@ static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
|
|||
{
|
||||
struct qeth_card *card = dev->ml_priv;
|
||||
struct qeth_arp_cache_entry arp_entry;
|
||||
enum qeth_arp_process_subcmds arp_cmd;
|
||||
int rc = 0;
|
||||
|
||||
switch (cmd) {
|
||||
|
@ -1893,27 +1864,16 @@ static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
|
|||
rc = qeth_l3_arp_query(card, rq->ifr_ifru.ifru_data);
|
||||
break;
|
||||
case SIOC_QETH_ARP_ADD_ENTRY:
|
||||
if (!capable(CAP_NET_ADMIN)) {
|
||||
rc = -EPERM;
|
||||
break;
|
||||
}
|
||||
if (copy_from_user(&arp_entry, rq->ifr_ifru.ifru_data,
|
||||
sizeof(struct qeth_arp_cache_entry)))
|
||||
rc = -EFAULT;
|
||||
else
|
||||
rc = qeth_l3_arp_add_entry(card, &arp_entry);
|
||||
break;
|
||||
case SIOC_QETH_ARP_REMOVE_ENTRY:
|
||||
if (!capable(CAP_NET_ADMIN)) {
|
||||
rc = -EPERM;
|
||||
break;
|
||||
}
|
||||
if (copy_from_user(&arp_entry, rq->ifr_ifru.ifru_data,
|
||||
sizeof(struct qeth_arp_cache_entry)))
|
||||
rc = -EFAULT;
|
||||
else
|
||||
rc = qeth_l3_arp_remove_entry(card, &arp_entry);
|
||||
break;
|
||||
if (!capable(CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
if (copy_from_user(&arp_entry, rq->ifr_data, sizeof(arp_entry)))
|
||||
return -EFAULT;
|
||||
|
||||
arp_cmd = (cmd == SIOC_QETH_ARP_ADD_ENTRY) ?
|
||||
IPA_CMD_ASS_ARP_ADD_ENTRY :
|
||||
IPA_CMD_ASS_ARP_REMOVE_ENTRY;
|
||||
return qeth_l3_arp_modify_entry(card, &arp_entry, arp_cmd);
|
||||
case SIOC_QETH_ARP_FLUSH_CACHE:
|
||||
if (!capable(CAP_NET_ADMIN)) {
|
||||
rc = -EPERM;
|
||||
|
|
Loading…
Reference in New Issue