Loading include/net/ip.h +4 −1 Original line number Diff line number Diff line Loading @@ -335,7 +335,10 @@ extern void ip_options_build(struct sk_buff *skb, struct ip_options *opt, u32 da extern int ip_options_echo(struct ip_options *dopt, struct sk_buff *skb); extern void ip_options_fragment(struct sk_buff *skb); extern int ip_options_compile(struct ip_options *opt, struct sk_buff *skb); extern int ip_options_get(struct ip_options **optp, unsigned char *data, int optlen, int user); extern int ip_options_get(struct ip_options **optp, unsigned char *data, int optlen); extern int ip_options_get_from_user(struct ip_options **optp, unsigned char __user *data, int optlen); extern void ip_options_undo(struct ip_options * opt); extern void ip_forward_options(struct sk_buff *skb); extern int ip_options_rcv_srr(struct sk_buff *skb); Loading net/ipv4/ip_options.c +34 −15 Original line number Diff line number Diff line Loading @@ -489,23 +489,18 @@ void ip_options_undo(struct ip_options * opt) } } int ip_options_get(struct ip_options **optp, unsigned char *data, int optlen, int user) static struct ip_options *ip_options_get_alloc(const int optlen) { struct ip_options *opt; opt = kmalloc(sizeof(struct ip_options)+((optlen+3)&~3), GFP_KERNEL); if (!opt) return -ENOMEM; memset(opt, 0, sizeof(struct ip_options)); if (optlen) { if (user) { if (copy_from_user(opt->__data, data, optlen)) { kfree(opt); return -EFAULT; } } else memcpy(opt->__data, data, optlen); struct ip_options *opt = kmalloc(sizeof(*opt) + ((optlen + 3) & ~3), GFP_KERNEL); if (opt) memset(opt, 0, sizeof(*opt)); return opt; } static int ip_options_get_finish(struct ip_options **optp, struct ip_options *opt, int optlen) { while (optlen & 3) opt->__data[optlen++] = IPOPT_END; opt->optlen = optlen; Loading @@ -521,6 +516,30 @@ int ip_options_get(struct ip_options **optp, unsigned char *data, int optlen, in return 0; } int ip_options_get_from_user(struct ip_options **optp, unsigned char __user *data, int optlen) { struct ip_options *opt = ip_options_get_alloc(optlen); if (!opt) return -ENOMEM; if (optlen && copy_from_user(opt->__data, data, optlen)) { kfree(opt); return -EFAULT; } return ip_options_get_finish(optp, opt, optlen); } int ip_options_get(struct ip_options **optp, unsigned char *data, int optlen) { struct ip_options *opt = ip_options_get_alloc(optlen); if (!opt) return -ENOMEM; if (optlen) memcpy(opt->__data, data, optlen); return ip_options_get_finish(optp, opt, optlen); } void ip_forward_options(struct sk_buff *skb) { struct ip_options * opt = &(IPCB(skb)->opt); Loading net/ipv4/ip_sockglue.c +2 −2 Original line number Diff line number Diff line Loading @@ -153,7 +153,7 @@ int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc) switch (cmsg->cmsg_type) { case IP_RETOPTS: err = cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr)); err = ip_options_get(&ipc->opt, CMSG_DATA(cmsg), err < 40 ? err : 40, 0); err = ip_options_get(&ipc->opt, CMSG_DATA(cmsg), err < 40 ? err : 40); if (err) return err; break; Loading Loading @@ -425,7 +425,7 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, struct ip_options * opt = NULL; if (optlen > 40 || optlen < 0) goto e_inval; err = ip_options_get(&opt, optval, optlen, 1); err = ip_options_get_from_user(&opt, optval, optlen); if (err) break; if (sk->sk_type == SOCK_STREAM) { Loading Loading
include/net/ip.h +4 −1 Original line number Diff line number Diff line Loading @@ -335,7 +335,10 @@ extern void ip_options_build(struct sk_buff *skb, struct ip_options *opt, u32 da extern int ip_options_echo(struct ip_options *dopt, struct sk_buff *skb); extern void ip_options_fragment(struct sk_buff *skb); extern int ip_options_compile(struct ip_options *opt, struct sk_buff *skb); extern int ip_options_get(struct ip_options **optp, unsigned char *data, int optlen, int user); extern int ip_options_get(struct ip_options **optp, unsigned char *data, int optlen); extern int ip_options_get_from_user(struct ip_options **optp, unsigned char __user *data, int optlen); extern void ip_options_undo(struct ip_options * opt); extern void ip_forward_options(struct sk_buff *skb); extern int ip_options_rcv_srr(struct sk_buff *skb); Loading
net/ipv4/ip_options.c +34 −15 Original line number Diff line number Diff line Loading @@ -489,23 +489,18 @@ void ip_options_undo(struct ip_options * opt) } } int ip_options_get(struct ip_options **optp, unsigned char *data, int optlen, int user) static struct ip_options *ip_options_get_alloc(const int optlen) { struct ip_options *opt; opt = kmalloc(sizeof(struct ip_options)+((optlen+3)&~3), GFP_KERNEL); if (!opt) return -ENOMEM; memset(opt, 0, sizeof(struct ip_options)); if (optlen) { if (user) { if (copy_from_user(opt->__data, data, optlen)) { kfree(opt); return -EFAULT; } } else memcpy(opt->__data, data, optlen); struct ip_options *opt = kmalloc(sizeof(*opt) + ((optlen + 3) & ~3), GFP_KERNEL); if (opt) memset(opt, 0, sizeof(*opt)); return opt; } static int ip_options_get_finish(struct ip_options **optp, struct ip_options *opt, int optlen) { while (optlen & 3) opt->__data[optlen++] = IPOPT_END; opt->optlen = optlen; Loading @@ -521,6 +516,30 @@ int ip_options_get(struct ip_options **optp, unsigned char *data, int optlen, in return 0; } int ip_options_get_from_user(struct ip_options **optp, unsigned char __user *data, int optlen) { struct ip_options *opt = ip_options_get_alloc(optlen); if (!opt) return -ENOMEM; if (optlen && copy_from_user(opt->__data, data, optlen)) { kfree(opt); return -EFAULT; } return ip_options_get_finish(optp, opt, optlen); } int ip_options_get(struct ip_options **optp, unsigned char *data, int optlen) { struct ip_options *opt = ip_options_get_alloc(optlen); if (!opt) return -ENOMEM; if (optlen) memcpy(opt->__data, data, optlen); return ip_options_get_finish(optp, opt, optlen); } void ip_forward_options(struct sk_buff *skb) { struct ip_options * opt = &(IPCB(skb)->opt); Loading
net/ipv4/ip_sockglue.c +2 −2 Original line number Diff line number Diff line Loading @@ -153,7 +153,7 @@ int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc) switch (cmsg->cmsg_type) { case IP_RETOPTS: err = cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr)); err = ip_options_get(&ipc->opt, CMSG_DATA(cmsg), err < 40 ? err : 40, 0); err = ip_options_get(&ipc->opt, CMSG_DATA(cmsg), err < 40 ? err : 40); if (err) return err; break; Loading Loading @@ -425,7 +425,7 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, struct ip_options * opt = NULL; if (optlen > 40 || optlen < 0) goto e_inval; err = ip_options_get(&opt, optval, optlen, 1); err = ip_options_get_from_user(&opt, optval, optlen); if (err) break; if (sk->sk_type == SOCK_STREAM) { Loading