* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
-
-#include <linux/config.h>
+
#include <linux/types.h>
#include <asm/atomic.h>
#include <asm/byteorder.h>
}
struct sock *__raw_v4_lookup(struct sock *sk, unsigned short num,
- unsigned long raddr, unsigned long laddr,
+ __be32 raddr, __be32 laddr,
int dif)
{
struct hlist_node *node;
}
err = -EPERM;
- if (!vx_check(0, VX_ADMIN) && !capable(CAP_NET_RAW)
+ if (!nx_check(0, VS_ADMIN) && !capable(CAP_NET_RAW)
&& (!addr_in_nx_info(sk->sk_nx_info, iph->saddr)))
goto error_free;
return err;
}
-static void raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
+static int raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
{
struct iovec *iov;
u8 __user *type = NULL;
unsigned int i;
if (!msg->msg_iov)
- return;
+ return 0;
for (i = 0; i < msg->msg_iovlen; i++) {
iov = &msg->msg_iov[i];
code = iov->iov_base;
if (type && code) {
- get_user(fl->fl_icmp_type, type);
- get_user(fl->fl_icmp_code, code);
+ if (get_user(fl->fl_icmp_type, type) ||
+ get_user(fl->fl_icmp_code, code))
+ return -EFAULT;
probed = 1;
}
break;
if (probed)
break;
}
+ return 0;
}
static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
struct ipcm_cookie ipc;
struct rtable *rt = NULL;
int free = 0;
- u32 daddr;
- u32 saddr;
+ __be32 daddr;
+ __be32 saddr;
u8 tos;
int err;
.proto = inet->hdrincl ? IPPROTO_RAW :
sk->sk_protocol,
};
- if (!inet->hdrincl)
- raw_probe_proto_opt(&fl, msg);
+ if (!inet->hdrincl) {
+ err = raw_probe_proto_opt(&fl, msg);
+ if (err)
+ goto done;
+ }
+ security_sk_classify_flow(sk, &fl);
if (sk->sk_nx_info) {
err = ip_find_src(sk->sk_nx_info, &rt, &fl);
if (sin) {
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = skb->nh.iph->saddr;
+ sin->sin_port = 0;
memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
}
if (inet->cmsg_flags)
out: return ret;
}
-static int raw_setsockopt(struct sock *sk, int level, int optname,
+static int do_raw_setsockopt(struct sock *sk, int level, int optname,
char __user *optval, int optlen)
{
- if (level != SOL_RAW)
- return ip_setsockopt(sk, level, optname, optval, optlen);
-
if (optname == ICMP_FILTER) {
if (inet_sk(sk)->num != IPPROTO_ICMP)
return -EOPNOTSUPP;
return -ENOPROTOOPT;
}
-static int raw_getsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int __user *optlen)
+static int raw_setsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int optlen)
{
if (level != SOL_RAW)
- return ip_getsockopt(sk, level, optname, optval, optlen);
+ return ip_setsockopt(sk, level, optname, optval, optlen);
+ return do_raw_setsockopt(sk, level, optname, optval, optlen);
+}
+#ifdef CONFIG_COMPAT
+static int compat_raw_setsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int optlen)
+{
+ if (level != SOL_RAW)
+ return compat_ip_setsockopt(sk, level, optname, optval, optlen);
+ return do_raw_setsockopt(sk, level, optname, optval, optlen);
+}
+#endif
+
+static int do_raw_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen)
+{
if (optname == ICMP_FILTER) {
if (inet_sk(sk)->num != IPPROTO_ICMP)
return -EOPNOTSUPP;
return -ENOPROTOOPT;
}
+static int raw_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen)
+{
+ if (level != SOL_RAW)
+ return ip_getsockopt(sk, level, optname, optval, optlen);
+ return do_raw_getsockopt(sk, level, optname, optval, optlen);
+}
+
+#ifdef CONFIG_COMPAT
+static int compat_raw_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen)
+{
+ if (level != SOL_RAW)
+ return compat_ip_getsockopt(sk, level, optname, optval, optlen);
+ return do_raw_getsockopt(sk, level, optname, optval, optlen);
+}
+#endif
+
static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg)
{
switch (cmd) {
}
struct proto raw_prot = {
- .name = "RAW",
- .owner = THIS_MODULE,
- .close = raw_close,
- .connect = ip4_datagram_connect,
- .disconnect = udp_disconnect,
- .ioctl = raw_ioctl,
- .init = raw_init,
- .setsockopt = raw_setsockopt,
- .getsockopt = raw_getsockopt,
- .sendmsg = raw_sendmsg,
- .recvmsg = raw_recvmsg,
- .bind = raw_bind,
- .backlog_rcv = raw_rcv_skb,
- .hash = raw_v4_hash,
- .unhash = raw_v4_unhash,
- .obj_size = sizeof(struct raw_sock),
+ .name = "RAW",
+ .owner = THIS_MODULE,
+ .close = raw_close,
+ .connect = ip4_datagram_connect,
+ .disconnect = udp_disconnect,
+ .ioctl = raw_ioctl,
+ .init = raw_init,
+ .setsockopt = raw_setsockopt,
+ .getsockopt = raw_getsockopt,
+ .sendmsg = raw_sendmsg,
+ .recvmsg = raw_recvmsg,
+ .bind = raw_bind,
+ .backlog_rcv = raw_rcv_skb,
+ .hash = raw_v4_hash,
+ .unhash = raw_v4_unhash,
+ .obj_size = sizeof(struct raw_sock),
+#ifdef CONFIG_COMPAT
+ .compat_setsockopt = compat_raw_setsockopt,
+ .compat_getsockopt = compat_raw_getsockopt,
+#endif
};
#ifdef CONFIG_PROC_FS
sk_for_each(sk, node, &raw_v4_htable[state->bucket])
if (sk->sk_family == PF_INET &&
- vx_check(sk->sk_xid, VX_IDENT|VX_WATCH))
+ nx_check(sk->sk_nid, VS_WATCH_P|VS_IDENT))
goto found;
}
sk = NULL;
try_again:
;
} while (sk && (sk->sk_family != PF_INET ||
- !vx_check(sk->sk_xid, VX_IDENT|VX_WATCH)));
+ !nx_check(sk->sk_nid, VS_WATCH_P|VS_IDENT)));
if (!sk && ++state->bucket < RAWV4_HTABLE_SIZE) {
sk = sk_head(&raw_v4_htable[state->bucket]);
static __inline__ char *get_raw_sock(struct sock *sp, char *tmpbuf, int i)
{
struct inet_sock *inet = inet_sk(sp);
- unsigned int dest = inet->daddr,
- src = inet->rcv_saddr;
+ __be32 dest = inet->daddr,
+ src = inet->rcv_saddr;
__u16 destp = 0,
srcp = inet->num;