Below patch puts struct sock into rose_cb to get rid of the need for the use of sk_protinfo in rose_sk(). While we're touching the data structure convert it from a typedef into a struct. ROSE wasn't verifying the ndigis argument of a new route resulting in a minor security hole. Minor cleanup and removed a too restrictive SCSI tape fix (http://marc.theaimsgroup.com/?l=linux-scsi&m=111497008818281&w=2) as of #85795 (http://bugs.gentoo.org/show_bug.cgi?id=85795). Signed-off-by: David S. Miller Signed-off-by: Lorenzo Hernandez Garcia-Hierro --- include/net/rose.h | 10 +++++--- net/rose/af_rose.c | 57 +++++++++++++++++--------------------------------- net/rose/rose_in.c | 10 ++++---- net/rose/rose_out.c | 6 ++--- net/rose/rose_route.c | 6 +++-- net/rose/rose_subr.c | 12 +++++----- net/rose/rose_timer.c | 14 ++++++------ 7 files changed, 51 insertions(+), 64 deletions(-) diff -puN include/net/rose.h~rose-fix include/net/rose.h --- linux-2.6.11/include/net/rose.h~rose-fix 2005-05-01 20:56:29.777381712 +0200 +++ linux-2.6.11-lorenzo/include/net/rose.h 2005-05-01 20:56:29.791379584 +0200 @@ -6,7 +6,9 @@ #ifndef _ROSE_H #define _ROSE_H + #include +#include #define ROSE_ADDR_LEN 5 @@ -114,7 +116,8 @@ struct rose_route { unsigned int rand; }; -typedef struct { +struct rose_sock { + struct sock sock; rose_address source_addr, dest_addr; ax25_address source_call, dest_call; unsigned char source_ndigis, dest_ndigis; @@ -135,10 +138,9 @@ typedef struct { struct rose_facilities_struct facilities; struct timer_list timer; struct timer_list idletimer; - struct sock *sk; /* Backlink to socket */ -} rose_cb; +}; -#define rose_sk(__sk) ((rose_cb *)(__sk)->sk_protinfo) +#define rose_sk(sk) ((struct rose_sock *)(sk)) /* af_rose.c */ extern ax25_address rose_callsign; diff -puN net/rose/af_rose.c~rose-fix net/rose/af_rose.c --- linux-2.6.11/net/rose/af_rose.c~rose-fix 2005-05-01 20:56:29.779381408 +0200 +++ linux-2.6.11-lorenzo/net/rose/af_rose.c 2005-05-01 20:56:29.792379432 +0200 @@ -128,24 +128,7 @@ int rosecmpm(rose_address *addr1, rose_a static struct sock *rose_alloc_sock(void) { - rose_cb *rose; - struct sock *sk = sk_alloc(PF_ROSE, GFP_ATOMIC, 1, NULL); - - if (!sk) - goto out; - - rose = sk->sk_protinfo = kmalloc(sizeof(*rose), GFP_ATOMIC); - if (!rose) - goto frees; - - memset(rose, 0x00, sizeof(*rose)); - rose->sk = sk; -out: - return sk; -frees: - sk_free(sk); - sk = NULL; - goto out; + return sk_alloc(PF_ROSE, GFP_ATOMIC, sizeof(struct rose_sock), NULL); } /* @@ -169,7 +152,7 @@ void rose_kill_by_neigh(struct rose_neig spin_lock_bh(&rose_list_lock); sk_for_each(s, node, &rose_list) { - rose_cb *rose = rose_sk(s); + struct rose_sock *rose = rose_sk(s); if (rose->neighbour == neigh) { rose_disconnect(s, ENETUNREACH, ROSE_OUT_OF_ORDER, 0); @@ -190,7 +173,7 @@ static void rose_kill_by_device(struct n spin_lock_bh(&rose_list_lock); sk_for_each(s, node, &rose_list) { - rose_cb *rose = rose_sk(s); + struct rose_sock *rose = rose_sk(s); if (rose->device == dev) { rose_disconnect(s, ENETUNREACH, ROSE_OUT_OF_ORDER, 0); @@ -247,7 +230,7 @@ static struct sock *rose_find_listener(r spin_lock_bh(&rose_list_lock); sk_for_each(s, node, &rose_list) { - rose_cb *rose = rose_sk(s); + struct rose_sock *rose = rose_sk(s); if (!rosecmp(&rose->source_addr, addr) && !ax25cmp(&rose->source_call, call) && @@ -256,7 +239,7 @@ static struct sock *rose_find_listener(r } sk_for_each(s, node, &rose_list) { - rose_cb *rose = rose_sk(s); + struct rose_sock *rose = rose_sk(s); if (!rosecmp(&rose->source_addr, addr) && !ax25cmp(&rose->source_call, &null_ax25_address) && @@ -279,7 +262,7 @@ struct sock *rose_find_socket(unsigned i spin_lock_bh(&rose_list_lock); sk_for_each(s, node, &rose_list) { - rose_cb *rose = rose_sk(s); + struct rose_sock *rose = rose_sk(s); if (rose->lci == lci && rose->neighbour == neigh) goto found; @@ -372,7 +355,7 @@ static int rose_setsockopt(struct socket char __user *optval, int optlen) { struct sock *sk = sock->sk; - rose_cb *rose = rose_sk(sk); + struct rose_sock *rose = rose_sk(sk); int opt; if (level != SOL_ROSE) @@ -432,7 +415,7 @@ static int rose_getsockopt(struct socket char __user *optval, int __user *optlen) { struct sock *sk = sock->sk; - rose_cb *rose = rose_sk(sk); + struct rose_sock *rose = rose_sk(sk); int val = 0; int len; @@ -491,7 +474,7 @@ static int rose_listen(struct socket *so struct sock *sk = sock->sk; if (sk->sk_state != TCP_LISTEN) { - rose_cb *rose = rose_sk(sk); + struct rose_sock *rose = rose_sk(sk); rose->dest_ndigis = 0; memset(&rose->dest_addr, 0, ROSE_ADDR_LEN); @@ -508,7 +491,7 @@ static int rose_listen(struct socket *so static int rose_create(struct socket *sock, int protocol) { struct sock *sk; - rose_cb *rose; + struct rose_sock *rose; if (sock->type != SOCK_SEQPACKET || protocol != 0) return -ESOCKTNOSUPPORT; @@ -547,7 +530,7 @@ static int rose_create(struct socket *so static struct sock *rose_make_new(struct sock *osk) { struct sock *sk; - rose_cb *rose, *orose; + struct rose_sock *rose, *orose; if (osk->sk_type != SOCK_SEQPACKET) return NULL; @@ -596,7 +579,7 @@ static struct sock *rose_make_new(struct static int rose_release(struct socket *sock) { struct sock *sk = sock->sk; - rose_cb *rose; + struct rose_sock *rose; if (sk == NULL) return 0; @@ -642,7 +625,7 @@ static int rose_release(struct socket *s static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) { struct sock *sk = sock->sk; - rose_cb *rose = rose_sk(sk); + struct rose_sock *rose = rose_sk(sk); struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr; struct net_device *dev; ax25_address *user, *source; @@ -701,7 +684,7 @@ static int rose_bind(struct socket *sock static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags) { struct sock *sk = sock->sk; - rose_cb *rose = rose_sk(sk); + struct rose_sock *rose = rose_sk(sk); struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr; unsigned char cause, diagnostic; ax25_address *user; @@ -902,7 +885,7 @@ static int rose_getname(struct socket *s { struct full_sockaddr_rose *srose = (struct full_sockaddr_rose *)uaddr; struct sock *sk = sock->sk; - rose_cb *rose = rose_sk(sk); + struct rose_sock *rose = rose_sk(sk); int n; if (peer != 0) { @@ -931,7 +914,7 @@ int rose_rx_call_request(struct sk_buff { struct sock *sk; struct sock *make; - rose_cb *make_rose; + struct rose_sock *make_rose; struct rose_facilities_struct facilities; int n, len; @@ -1012,7 +995,7 @@ static int rose_sendmsg(struct kiocb *io struct msghdr *msg, size_t len) { struct sock *sk = sock->sk; - rose_cb *rose = rose_sk(sk); + struct rose_sock *rose = rose_sk(sk); struct sockaddr_rose *usrose = (struct sockaddr_rose *)msg->msg_name; int err; struct full_sockaddr_rose srose; @@ -1182,7 +1165,7 @@ static int rose_recvmsg(struct kiocb *io struct msghdr *msg, size_t size, int flags) { struct sock *sk = sock->sk; - rose_cb *rose = rose_sk(sk); + struct rose_sock *rose = rose_sk(sk); struct sockaddr_rose *srose = (struct sockaddr_rose *)msg->msg_name; size_t copied; unsigned char *asmptr; @@ -1247,7 +1230,7 @@ static int rose_recvmsg(struct kiocb *io static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { struct sock *sk = sock->sk; - rose_cb *rose = rose_sk(sk); + struct rose_sock *rose = rose_sk(sk); void __user *argp = (void __user *)arg; switch (cmd) { @@ -1382,7 +1365,7 @@ static int rose_info_show(struct seq_fil else { struct sock *s = v; - rose_cb *rose = rose_sk(s); + struct rose_sock *rose = rose_sk(s); const char *devname, *callsign; const struct net_device *dev = rose->device; diff -puN net/rose/rose_in.c~rose-fix net/rose/rose_in.c --- linux-2.6.11/net/rose/rose_in.c~rose-fix 2005-05-01 20:56:29.781381104 +0200 +++ linux-2.6.11-lorenzo/net/rose/rose_in.c 2005-05-01 20:56:29.792379432 +0200 @@ -41,7 +41,7 @@ */ static int rose_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype) { - rose_cb *rose = rose_sk(sk); + struct rose_sock *rose = rose_sk(sk); switch (frametype) { case ROSE_CALL_ACCEPTED: @@ -78,7 +78,7 @@ static int rose_state1_machine(struct so */ static int rose_state2_machine(struct sock *sk, struct sk_buff *skb, int frametype) { - rose_cb *rose = rose_sk(sk); + struct rose_sock *rose = rose_sk(sk); switch (frametype) { case ROSE_CLEAR_REQUEST: @@ -106,7 +106,7 @@ static int rose_state2_machine(struct so */ static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype, int ns, int nr, int q, int d, int m) { - rose_cb *rose = rose_sk(sk); + struct rose_sock *rose = rose_sk(sk); int queued = 0; switch (frametype) { @@ -216,7 +216,7 @@ static int rose_state3_machine(struct so */ static int rose_state4_machine(struct sock *sk, struct sk_buff *skb, int frametype) { - rose_cb *rose = rose_sk(sk); + struct rose_sock *rose = rose_sk(sk); switch (frametype) { case ROSE_RESET_REQUEST: @@ -265,7 +265,7 @@ static int rose_state5_machine(struct so /* Higher level upcall for a LAPB frame */ int rose_process_rx_frame(struct sock *sk, struct sk_buff *skb) { - rose_cb *rose = rose_sk(sk); + struct rose_sock *rose = rose_sk(sk); int queued = 0, frametype, ns, nr, q, d, m; if (rose->state == ROSE_STATE_0) diff -puN net/rose/rose_out.c~rose-fix net/rose/rose_out.c --- linux-2.6.11/net/rose/rose_out.c~rose-fix 2005-05-01 20:56:29.783380800 +0200 +++ linux-2.6.11-lorenzo/net/rose/rose_out.c 2005-05-01 20:56:29.793379280 +0200 @@ -33,7 +33,7 @@ */ static void rose_send_iframe(struct sock *sk, struct sk_buff *skb) { - rose_cb *rose = rose_sk(sk); + struct rose_sock *rose = rose_sk(sk); if (skb == NULL) return; @@ -48,7 +48,7 @@ static void rose_send_iframe(struct sock void rose_kick(struct sock *sk) { - rose_cb *rose = rose_sk(sk); + struct rose_sock *rose = rose_sk(sk); struct sk_buff *skb, *skbn; unsigned short start, end; @@ -112,7 +112,7 @@ void rose_kick(struct sock *sk) void rose_enquiry_response(struct sock *sk) { - rose_cb *rose = rose_sk(sk); + struct rose_sock *rose = rose_sk(sk); if (rose->condition & ROSE_COND_OWN_RX_BUSY) rose_write_internal(sk, ROSE_RNR); diff -puN net/rose/rose_route.c~rose-fix net/rose/rose_route.c --- linux-2.6.11/net/rose/rose_route.c~rose-fix 2005-05-01 20:56:29.784380648 +0200 +++ linux-2.6.11-lorenzo/net/rose/rose_route.c 2005-05-01 20:56:29.793379280 +0200 @@ -727,7 +727,8 @@ int rose_rt_ioctl(unsigned int cmd, void } if (rose_route.mask > 10) /* Mask can't be more than 10 digits */ return -EINVAL; - + if (rose_route.ndigis > 8) /* No more than 8 digipeats */ + return -EINVAL; err = rose_add_node(&rose_route, dev); dev_put(dev); return err; @@ -898,7 +899,8 @@ int rose_route_frame(struct sk_buff *skb */ if ((sk = rose_find_socket(lci, rose_neigh)) != NULL) { if (frametype == ROSE_CALL_REQUEST) { - rose_cb *rose = rose_sk(sk); + struct rose_sock *rose = rose_sk(sk); + /* Remove an existing unused socket */ rose_clear_queues(sk); rose->cause = ROSE_NETWORK_CONGESTION; diff -puN net/rose/rose_subr.c~rose-fix net/rose/rose_subr.c --- linux-2.6.11/net/rose/rose_subr.c~rose-fix 2005-05-01 20:56:29.786380344 +0200 +++ linux-2.6.11-lorenzo/net/rose/rose_subr.c 2005-05-01 20:56:29.794379128 +0200 @@ -28,7 +28,7 @@ #include #include -static int rose_create_facilities(unsigned char *buffer, rose_cb *rose); +static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose); /* * This routine purges all of the queues of frames. @@ -47,7 +47,7 @@ void rose_clear_queues(struct sock *sk) void rose_frames_acked(struct sock *sk, unsigned short nr) { struct sk_buff *skb; - rose_cb *rose = rose_sk(sk); + struct rose_sock *rose = rose_sk(sk); /* * Remove all the ack-ed frames from the ack queue. @@ -85,7 +85,7 @@ void rose_requeue_frames(struct sock *sk */ int rose_validate_nr(struct sock *sk, unsigned short nr) { - rose_cb *rose = rose_sk(sk); + struct rose_sock *rose = rose_sk(sk); unsigned short vc = rose->va; while (vc != rose->vs) { @@ -102,7 +102,7 @@ int rose_validate_nr(struct sock *sk, un */ void rose_write_internal(struct sock *sk, int frametype) { - rose_cb *rose = rose_sk(sk); + struct rose_sock *rose = rose_sk(sk); struct sk_buff *skb; unsigned char *dptr; unsigned char lci1, lci2; @@ -396,7 +396,7 @@ int rose_parse_facilities(unsigned char return 1; } -static int rose_create_facilities(unsigned char *buffer, rose_cb *rose) +static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose) { unsigned char *p = buffer + 1; char *callsign; @@ -492,7 +492,7 @@ static int rose_create_facilities(unsign void rose_disconnect(struct sock *sk, int reason, int cause, int diagnostic) { - rose_cb *rose = rose_sk(sk); + struct rose_sock *rose = rose_sk(sk); rose_stop_timer(sk); rose_stop_idletimer(sk); diff -puN net/rose/rose_timer.c~rose-fix net/rose/rose_timer.c --- linux-2.6.11/net/rose/rose_timer.c~rose-fix 2005-05-01 20:56:29.788380040 +0200 +++ linux-2.6.11-lorenzo/net/rose/rose_timer.c 2005-05-01 20:56:29.794379128 +0200 @@ -46,7 +46,7 @@ void rose_start_heartbeat(struct sock *s void rose_start_t1timer(struct sock *sk) { - rose_cb *rose = rose_sk(sk); + struct rose_sock *rose = rose_sk(sk); del_timer(&rose->timer); @@ -59,7 +59,7 @@ void rose_start_t1timer(struct sock *sk) void rose_start_t2timer(struct sock *sk) { - rose_cb *rose = rose_sk(sk); + struct rose_sock *rose = rose_sk(sk); del_timer(&rose->timer); @@ -72,7 +72,7 @@ void rose_start_t2timer(struct sock *sk) void rose_start_t3timer(struct sock *sk) { - rose_cb *rose = rose_sk(sk); + struct rose_sock *rose = rose_sk(sk); del_timer(&rose->timer); @@ -85,7 +85,7 @@ void rose_start_t3timer(struct sock *sk) void rose_start_hbtimer(struct sock *sk) { - rose_cb *rose = rose_sk(sk); + struct rose_sock *rose = rose_sk(sk); del_timer(&rose->timer); @@ -98,7 +98,7 @@ void rose_start_hbtimer(struct sock *sk) void rose_start_idletimer(struct sock *sk) { - rose_cb *rose = rose_sk(sk); + struct rose_sock *rose = rose_sk(sk); del_timer(&rose->idletimer); @@ -129,7 +129,7 @@ void rose_stop_idletimer(struct sock *sk static void rose_heartbeat_expiry(unsigned long param) { struct sock *sk = (struct sock *)param; - rose_cb *rose = rose_sk(sk); + struct rose_sock *rose = rose_sk(sk); bh_lock_sock(sk); switch (rose->state) { @@ -166,7 +166,7 @@ static void rose_heartbeat_expiry(unsign static void rose_timer_expiry(unsigned long param) { struct sock *sk = (struct sock *)param; - rose_cb *rose = rose_sk(sk); + struct rose_sock *rose = rose_sk(sk); bh_lock_sock(sk); switch (rose->state) { _