diff -NurP --minimal linux-2.4.23-pre4/include/net/route.h linux-2.4.23-pre4-ctx17d/include/net/route.h --- linux-2.4.23-pre4/include/net/route.h 2003-08-25 20:32:20.000000000 +0200 +++ linux-2.4.23-pre4-ctx17d/include/net/route.h 2003-09-13 17:19:02.000000000 +0200 @@ -166,6 +166,43 @@ static inline int ip_route_connect(struct rtable **rp, u32 dst, u32 src, u32 tos, int oif) { int err; + struct iproot_info *ip_info = current->ip_info; + if (ip_info != NULL) { + __u32 ipv4root = ip_info->ipv4[0]; + if (ipv4root != 0) { + int n=ip_info->nbipv4; + if (src == 0) { + if (n > 1) { + u32 foundsrc; + int i; + err = ip_route_output(rp, dst, src, tos, oif); + if (err) return err; + foundsrc = (*rp)->rt_src; + for (i=0; imask[i]; + u32 ipv4 = ip_info->ipv4[i]; + u32 netipv4 = ipv4 & mask; + if ((foundsrc & mask) == netipv4) { + src = ipv4; + break; + } + } + } + if (src == 0) + src = dst == 0x0100007f + ? 0x0100007f: ipv4root; + } else { + int i; + for (i=0; iipv4[i] == src) break; + } + if (i==n) + return -EPERM; + } + if (dst == 0x0100007f && current->s_context != 0) + dst = ipv4root; + } + } err = ip_route_output(rp, dst, src, tos, oif); if (err || (dst && src)) return err; diff -NurP --minimal linux-2.4.23-pre4/include/net/sock.h linux-2.4.23-pre4-ctx17d/include/net/sock.h --- linux-2.4.23-pre4/include/net/sock.h 2003-08-15 01:25:27.000000000 +0200 +++ linux-2.4.23-pre4-ctx17d/include/net/sock.h 2003-09-13 15:54:05.000000000 +0200 @@ -498,6 +498,7 @@ } while(0) struct sock { + /* See tcp.h comment on tcp_tw_bucket */ /* Socket demultiplex comparisons on incoming packets. */ __u32 daddr; /* Foreign IPv4 addr */ __u32 rcv_saddr; /* Bound local IPv4 addr */ @@ -519,6 +520,8 @@ unsigned char reuse; /* SO_REUSEADDR setting */ unsigned char shutdown; atomic_t refcnt; /* Reference count */ + struct iproot_info *ip_info; + /* End of common section with tcp_tw_bucket */ socket_lock_t lock; /* Synchronizer... */ int rcvbuf; /* Size of receive buffer in bytes */ @@ -536,6 +539,7 @@ __u32 saddr; /* Sending source */ unsigned int allocation; /* Allocation mode */ int sndbuf; /* Size of send buffer in bytes */ + __u32 rcv_saddr2; /* Second bound ipv4 addr, for ipv4root */ struct sock *prev; /* Not all are volatile, but some are, so we might as well say they all are. @@ -680,6 +684,9 @@ /* RPC layer private data */ void *user_data; + /* Context of process creating this socket */ + int s_context; + /* Callbacks */ void (*state_change)(struct sock *sk); void (*data_ready)(struct sock *sk,int bytes); diff -NurP --minimal linux-2.4.23-pre4/include/net/tcp.h linux-2.4.23-pre4-ctx17d/include/net/tcp.h --- linux-2.4.23-pre4/include/net/tcp.h 2003-08-25 20:32:20.000000000 +0200 +++ linux-2.4.23-pre4-ctx17d/include/net/tcp.h 2003-09-13 15:56:15.000000000 +0200 @@ -173,6 +173,7 @@ unsigned char reuse, rcv_wscale; /* It is also TW bucket specific */ atomic_t refcnt; + struct ipv4_info *ip_info; /* And these are ours. */ int hashent; @@ -191,6 +192,7 @@ struct in6_addr v6_daddr; struct in6_addr v6_rcv_saddr; #endif + int s_context; }; extern kmem_cache_t *tcp_timewait_cachep; diff -NurP --minimal linux-2.4.23-pre4/ipc/util.c linux-2.4.23-pre4-ctx17d/ipc/util.c --- linux-2.4.23-pre4/ipc/util.c 2003-08-25 20:32:20.000000000 +0200 +++ linux-2.4.23-pre4-ctx17d/ipc/util.c 2003-09-13 17:19:02.000000000 +0200 @@ -93,6 +93,8 @@ struct kern_ipc_perm* p; for (id = 0; id <= ids->max_id; id++) { + if (ids->entries[id].s_context != current->s_context) + continue; p = ids->entries[id].p; if(p==NULL) continue; @@ -167,6 +169,7 @@ spin_lock(&ids->ary); ids->entries[id].p = new; + ids->entries[id].s_context = current->s_context; return id; } diff -NurP --minimal linux-2.4.23-pre4/net/ipv4/af_inet.c linux-2.4.23-pre4-ctx17d/net/ipv4/af_inet.c --- linux-2.4.23-pre4/net/ipv4/af_inet.c 2003-06-13 16:51:39.000000000 +0200 +++ linux-2.4.23-pre4-ctx17d/net/ipv4/af_inet.c 2003-09-13 17:19:02.000000000 +0200 @@ -177,6 +177,8 @@ if (sk->protinfo.af_inet.opt) kfree(sk->protinfo.af_inet.opt); + sys_release_ip_info(sk->ip_info); + sk->ip_info = NULL; dst_release(sk->dst_cache); #ifdef INET_REFCNT_DEBUG atomic_dec(&inet_sock_nr); @@ -393,6 +395,9 @@ sk->protinfo.af_inet.mc_index = 0; sk->protinfo.af_inet.mc_list = NULL; + sk->s_context = current->s_context; + sk->ip_info = NULL; + #ifdef INET_REFCNT_DEBUG atomic_inc(&inet_sock_nr); #endif @@ -477,6 +482,11 @@ unsigned short snum; int chk_addr_ret; int err; + __u32 s_addr; /* Address used for validation */ + __u32 s_addr1; + __u32 s_addr2 = 0xffffffffl; /* Optional address of the socket */ + /* bcast in ipv4root world */ + struct iproot_info *ip_info; /* If the socket has its own bind function then use it. (RAW) */ if(sk->prot->bind) @@ -485,7 +495,37 @@ if (addr_len < sizeof(struct sockaddr_in)) return -EINVAL; - chk_addr_ret = inet_addr_type(addr->sin_addr.s_addr); + s_addr = s_addr1 = addr->sin_addr.s_addr; + ip_info = current->ip_info; + if (ip_info) { + __u32 v4_bcast = ip_info->v4_bcast; + __u32 ipv4root = ip_info->ipv4[0]; + int nbipv4 = ip_info->nbipv4; + if (s_addr == 0) { + s_addr = ipv4root; + if (nbipv4 > 1) + s_addr1 = 0; + else { + s_addr1 = ipv4root; + ip_info = NULL; + } + s_addr2 = v4_bcast; + } else if (s_addr == 0x0100007f) { + s_addr = s_addr1 = ipv4root; + ip_info = NULL; + } else if (s_addr != v4_bcast + && s_addr != ipv4root) { + int i; + for (i=0; iipv4[i]) + break; + } + if (i == nbipv4) + return -EADDRNOTAVAIL; + ip_info = NULL; + } + } + chk_addr_ret = inet_addr_type(s_addr); /* Not specified by any standard per-se, however it breaks too * many applications when removed. It is unfortunate since @@ -496,7 +536,7 @@ */ if (sysctl_ip_nonlocal_bind == 0 && sk->protinfo.af_inet.freebind == 0 && - addr->sin_addr.s_addr != INADDR_ANY && + s_addr != INADDR_ANY && chk_addr_ret != RTN_LOCAL && chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST) @@ -521,13 +561,19 @@ (sk->num != 0)) goto out; - sk->rcv_saddr = sk->saddr = addr->sin_addr.s_addr; + sk->rcv_saddr = sk->saddr = s_addr1; + sk->rcv_saddr2 = s_addr2; + sk->ip_info = ip_info; + if (ip_info) + sys_assign_ip_info(ip_info); if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST) sk->saddr = 0; /* Use device */ /* Make sure we are allowed to bind here. */ if (sk->prot->get_port(sk, snum) != 0) { sk->saddr = sk->rcv_saddr = 0; + sk->ip_info = NULL; + sys_release_ip_info(ip_info); err = -EADDRINUSE; goto out; } diff -NurP --minimal linux-2.4.23-pre4/net/ipv4/devinet.c linux-2.4.23-pre4-ctx17d/net/ipv4/devinet.c --- linux-2.4.23-pre4/net/ipv4/devinet.c 2003-09-13 00:50:17.000000000 +0200 +++ linux-2.4.23-pre4-ctx17d/net/ipv4/devinet.c 2003-09-13 17:19:02.000000000 +0200 @@ -455,6 +455,32 @@ return -1; } +/* + Check that a device is not member of the ipv4root assigned to the process + Return true if this is the case + + If the process is not bound to specific IP, then it returns 0 (all + interface are fine). +*/ +static int devinet_notiproot (struct in_ifaddr *ifa) +{ + int ret = 0; + struct iproot_info *info = current->ip_info; + if (current->s_context && info) { + int i; + int nbip = info->nbipv4; + __u32 addr = ifa->ifa_local; + ret = 1; + for (i=0; iipv4[i] == addr) { + ret = 0; + break; + } + } + } + return ret; +} + int devinet_ioctl(unsigned int cmd, void *arg) { @@ -558,7 +584,11 @@ ret = -EADDRNOTAVAIL; goto done; } - + if (ifa != NULL + && devinet_notiproot(ifa)) { + ret = -EADDRNOTAVAIL; + goto done; + } switch(cmd) { case SIOCGIFADDR: /* Get interface address */ sin->sin_addr.s_addr = ifa->ifa_local; @@ -691,6 +721,9 @@ return 0; for ( ; ifa; ifa = ifa->ifa_next) { + // We do not show other IP devices to vservers + if (devinet_notiproot(ifa)) + continue; if (!buf) { done += sizeof(ifr); continue; @@ -933,6 +966,8 @@ read_lock(&in_dev->lock); for (ifa = in_dev->ifa_list, ip_idx = 0; ifa; ifa = ifa->ifa_next, ip_idx++) { + if (devinet_notiproot(ifa)) + continue; if (ip_idx < s_ip_idx) continue; if (inet_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid, diff -NurP --minimal linux-2.4.23-pre4/net/ipv4/raw.c linux-2.4.23-pre4-ctx17d/net/ipv4/raw.c --- linux-2.4.23-pre4/net/ipv4/raw.c 2003-08-25 20:32:24.000000000 +0200 +++ linux-2.4.23-pre4-ctx17d/net/ipv4/raw.c 2003-09-13 17:19:02.000000000 +0200 @@ -96,16 +96,47 @@ write_unlock_bh(&raw_v4_lock); } + +/* + Check if an address is in the list +*/ +static inline int raw_addr_in_list ( + u32 rcv_saddr1, + u32 rcv_saddr2, + u32 loc_addr, + struct iproot_info *ip_info) +{ + int ret = 0; + if (loc_addr != 0 && + (rcv_saddr1 == loc_addr || rcv_saddr2 == loc_addr)) + ret = 1; + else if (rcv_saddr1 == 0) { + /* Accept any address or only the one in the list */ + if (ip_info == NULL) + ret = 1; + else { + int n = ip_info->nbipv4; + int i; + for (i=0; iipv4[i] == loc_addr) { + ret = 1; + break; + } + } + } + } + return ret; +} + struct sock *__raw_v4_lookup(struct sock *sk, unsigned short num, unsigned long raddr, unsigned long laddr, int dif) { struct sock *s = sk; - for (s = sk; s; s = s->next) { if (s->num == num && !(s->daddr && s->daddr != raddr) && - !(s->rcv_saddr && s->rcv_saddr != laddr) && + raw_addr_in_list(s->rcv_saddr,s->rcv_saddr2,laddr,s->ip_info) && !(s->bound_dev_if && s->bound_dev_if != dif)) break; /* gotcha */ } @@ -657,7 +688,7 @@ struct sock *sk; for (sk = raw_v4_htable[i]; sk; sk = sk->next, num++) { - if (sk->family != PF_INET) + if (sk->family != PF_INET || (current->s_context != 1 && sk->s_context != current->s_context)) continue; pos += 128; if (pos <= offset) diff -NurP --minimal linux-2.4.23-pre4/net/ipv4/tcp_ipv4.c linux-2.4.23-pre4-ctx17d/net/ipv4/tcp_ipv4.c --- linux-2.4.23-pre4/net/ipv4/tcp_ipv4.c 2003-08-25 20:32:24.000000000 +0200 +++ linux-2.4.23-pre4-ctx17d/net/ipv4/tcp_ipv4.c 2003-09-13 17:19:02.000000000 +0200 @@ -180,6 +180,55 @@ sk->prev = (struct sock *) tb; } +/* + Return 1 if addr match the socket IP list + or the socket is INADDR_ANY +*/ +static inline int tcp_in_list (struct sock *sk, u32 addr) +{ + int ret = 0; + struct iproot_info *ip_info = sk->ip_info; + if (ip_info != NULL){ + int n = ip_info->nbipv4; + int i; + for (i=0; iipv4[i] == addr) { + ret = 1; + break; + } + } + } else if (!sk->rcv_saddr || sk->rcv_saddr == addr) { + ret = 1; + } + return ret; +} + +/* + Check if the addresses in sk1 conflict with those in sk2 +*/ +int tcp_ipv4_addr_conflict (struct sock *sk1, struct sock *sk2) +{ + int ret = 0; + if (sk1->rcv_saddr) + /* Bind to one address only */ + ret = tcp_in_list (sk2,sk1->rcv_saddr); + else if (sk1->ip_info) { + /* A restricted bind(any) */ + struct iproot_info *ip_info = sk1->ip_info; + int n = ip_info->nbipv4; + int i; + for (i=0; iipv4[i])) { + ret = 1; + break; + } + } + } + else /* A bind(any) do not allow other bind on the same port */ + ret = 1; + return ret; +} + static inline int tcp_bind_conflict(struct sock *sk, struct tcp_bind_bucket *tb) { struct sock *sk2 = tb->owners; @@ -193,9 +242,7 @@ if (!sk_reuse || !sk2->reuse || sk2->state == TCP_LISTEN) { - if (!sk2->rcv_saddr || - !sk->rcv_saddr || - (sk2->rcv_saddr == sk->rcv_saddr)) + if (tcp_ipv4_addr_conflict(sk,sk2)) break; } } @@ -414,6 +461,37 @@ wake_up(&tcp_lhash_wait); } +/* + Check if an address is in the list +*/ +static inline int tcp_addr_in_list ( + u32 rcv_saddr, + u32 daddr, + struct iproot_info *ip_info) +{ + int ret = 0; + if (rcv_saddr == daddr) + ret = 1; + else if (rcv_saddr == 0) { + /* Accept any address or only the one in the list */ + if (ip_info == NULL) + ret = 1; + else { + int n = ip_info->nbipv4; + int i; + for (i=0; iipv4[i] == daddr) { + ret = 1; + break; + } + } + } + } + return ret; +} + + + /* Don't inline this cruft. Here are some nice properties to * exploit here. The BSD API does not allow a listening TCP * to specify the remote port nor the remote address for the @@ -435,10 +513,10 @@ #else score = 1; #endif - if(rcv_saddr) { - if (rcv_saddr != daddr) - continue; + if (tcp_addr_in_list(rcv_saddr,daddr,sk->ip_info)) score+=2; + else + continue; } if (sk->bound_dev_if) { if (sk->bound_dev_if != dif) @@ -466,8 +544,8 @@ if (sk) { if (sk->num == hnum && sk->next == NULL && - (!sk->rcv_saddr || sk->rcv_saddr == daddr) && (sk->family == PF_INET || !ipv6_only_sock(sk)) && + tcp_addr_in_list(sk->rcv_saddr,daddr,sk->ip_info) && !sk->bound_dev_if) goto sherry_cache; sk = __tcp_v4_lookup_listener(sk, daddr, hnum, dif); @@ -2189,6 +2267,9 @@ int uid; struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + if (current->s_context != 1 && sk->s_context != current->s_context) + continue; + if (!TCP_INET_FAMILY(sk->family)) goto skip_listen; @@ -2242,7 +2323,8 @@ read_lock(&head->lock); for(sk = head->chain; sk; sk = sk->next, num++) { - if (!TCP_INET_FAMILY(sk->family)) + if (!TCP_INET_FAMILY(sk->family) || + (current->s_context != 1 && sk->s_context != current->s_context)) continue; pos += TMPSZ; if (pos <= offset) @@ -2257,7 +2339,8 @@ for (tw = (struct tcp_tw_bucket *)tcp_ehash[i+tcp_ehash_size].chain; tw != NULL; tw = (struct tcp_tw_bucket *)tw->next, num++) { - if (!TCP_INET_FAMILY(tw->family)) + if (!TCP_INET_FAMILY(tw->family) || + (current->s_context != 1 && tw->s_context != current->s_context)) continue; pos += TMPSZ; if (pos <= offset) diff -NurP --minimal linux-2.4.23-pre4/net/ipv4/tcp_minisocks.c linux-2.4.23-pre4-ctx17d/net/ipv4/tcp_minisocks.c --- linux-2.4.23-pre4/net/ipv4/tcp_minisocks.c 2003-08-25 20:32:24.000000000 +0200 +++ linux-2.4.23-pre4-ctx17d/net/ipv4/tcp_minisocks.c 2003-09-13 17:19:02.000000000 +0200 @@ -380,6 +380,9 @@ tw->ts_recent_stamp= tp->ts_recent_stamp; tw->pprev_death = NULL; + tw->s_context = sk->s_context; + tw->ip_info = NULL; + #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) if(tw->family == PF_INET6) { memcpy(&tw->v6_daddr, @@ -651,6 +654,7 @@ #endif memcpy(newsk, sk, sizeof(*newsk)); + sys_assign_ip_info(newsk->ip_info); newsk->state = TCP_SYN_RECV; /* SANITY */ diff -NurP --minimal linux-2.4.23-pre4/net/ipv4/udp.c linux-2.4.23-pre4-ctx17d/net/ipv4/udp.c --- linux-2.4.23-pre4/net/ipv4/udp.c 2003-08-25 20:32:24.000000000 +0200 +++ linux-2.4.23-pre4-ctx17d/net/ipv4/udp.c 2003-09-13 17:19:02.000000000 +0200 @@ -110,6 +110,9 @@ /* Shared by v4/v6 udp. */ int udp_port_rover; +int tcp_ipv4_addr_conflict (struct sock *sk1, struct sock *sk2); + + static int udp_v4_get_port(struct sock *sk, unsigned short snum) { write_lock_bh(&udp_hash_lock); @@ -165,9 +168,7 @@ sk2 != sk && !ipv6_only_sock(sk2) && sk2->bound_dev_if == sk->bound_dev_if && - (!sk2->rcv_saddr || - !sk->rcv_saddr || - sk2->rcv_saddr == sk->rcv_saddr) && + tcp_ipv4_addr_conflict (sk2,sk) && (!sk2->reuse || !sk->reuse)) goto fail; } @@ -210,6 +211,20 @@ write_unlock_bh(&udp_hash_lock); } +static int udp_in_list (struct iproot_info *ip_info, u32 addr) +{ + int ret = 0; + int n = ip_info->nbipv4; + int i; + for (i=0; iipv4[i] == addr) { + ret = 1; + break; + } + } + return ret; +} + /* UDP is nearly always wildcards out the wazoo, it makes no sense to try * harder than this. -DaveM */ @@ -231,6 +246,11 @@ if(sk->rcv_saddr != daddr) continue; score+=2; + } else if (sk->ip_info) { + if (udp_in_list (sk->ip_info,daddr)) + score++; + else + continue; } if(sk->daddr) { if(sk->daddr != saddr) @@ -284,7 +304,7 @@ if ((s->num != hnum) || (s->daddr && s->daddr!=rmt_addr) || (s->dport != rmt_port && s->dport != 0) || - (s->rcv_saddr && s->rcv_saddr != loc_addr) || + (s->rcv_saddr && s->rcv_saddr != loc_addr && s->rcv_saddr2 != loc_addr) || ipv6_only_sock(s) || (s->bound_dev_if && s->bound_dev_if != dif)) continue; @@ -532,6 +552,16 @@ rt = (struct rtable*)sk_dst_check(sk, 0); if (rt == NULL) { + struct iproot_info *ip_info = current->ip_info; + if (ip_info != NULL) { + __u32 ipv4root = ip_info->ipv4[0]; + if (ipv4root) { + if (daddr == 0x0100007f && current->s_context != 0) + daddr = ipv4root; + if (ufh.saddr == 0) + ufh.saddr = ipv4root; + } + } err = ip_route_output(&rt, daddr, ufh.saddr, tos, ipc.oif); if (err) goto out; @@ -1019,7 +1049,8 @@ struct sock *sk; for (sk = udp_hash[i]; sk; sk = sk->next, num++) { - if (sk->family != PF_INET) + if (sk->family != PF_INET || + (current->s_context != 1 && sk->s_context != current->s_context)) continue; pos += 128; if (pos <= offset) diff -NurP --minimal linux-2.4.23-pre4/net/ipv6/raw.c linux-2.4.23-pre4-ctx17d/net/ipv6/raw.c --- linux-2.4.23-pre4/net/ipv6/raw.c 2003-09-13 00:50:17.000000000 +0200 +++ linux-2.4.23-pre4-ctx17d/net/ipv6/raw.c 2003-09-13 17:19:02.000000000 +0200 @@ -880,7 +880,8 @@ struct sock *sk; for (sk = raw_v6_htable[i]; sk; sk = sk->next, num++) { - if (sk->family != PF_INET6) + if (sk->family != PF_INET6 || + (current->s_context != 1 && sk->s_context != current->s_context)) continue; pos += LINE_LEN+1; if (pos <= offset) diff -NurP --minimal linux-2.4.23-pre4/net/ipv6/tcp_ipv6.c linux-2.4.23-pre4-ctx17d/net/ipv6/tcp_ipv6.c --- linux-2.4.23-pre4/net/ipv6/tcp_ipv6.c 2003-08-25 20:32:25.000000000 +0200 +++ linux-2.4.23-pre4-ctx17d/net/ipv6/tcp_ipv6.c 2003-09-13 17:19:02.000000000 +0200 @@ -2027,7 +2027,8 @@ int uid; struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); - if (sk->family != PF_INET6) + if (sk->family != PF_INET6 || + (current->s_context != 1 && sk->s_context != current->s_context)) continue; pos += LINE_LEN+1; if (pos >= offset) { @@ -2077,7 +2078,8 @@ read_lock(&head->lock); for(sk = head->chain; sk; sk = sk->next, num++) { - if (sk->family != PF_INET6) + if (sk->family != PF_INET6 || + (current->s_context != 1 && sk->s_context != current->s_context)) continue; pos += LINE_LEN+1; if (pos <= offset) @@ -2092,7 +2094,8 @@ for (tw = (struct tcp_tw_bucket *)tcp_ehash[i+tcp_ehash_size].chain; tw != NULL; tw = (struct tcp_tw_bucket *)tw->next, num++) { - if (tw->family != PF_INET6) + if (tw->family != PF_INET6 || + (current->s_context != 1 && tw->s_context != current->s_context)) continue; pos += LINE_LEN+1; if (pos <= offset) diff -NurP --minimal linux-2.4.23-pre4/net/ipv6/udp.c linux-2.4.23-pre4-ctx17d/net/ipv6/udp.c --- linux-2.4.23-pre4/net/ipv6/udp.c 2003-08-25 20:32:25.000000000 +0200 +++ linux-2.4.23-pre4-ctx17d/net/ipv6/udp.c 2003-09-13 17:19:02.000000000 +0200 @@ -979,7 +979,8 @@ struct sock *sk; for (sk = udp_hash[i]; sk; sk = sk->next, num++) { - if (sk->family != PF_INET6) + if (sk->family != PF_INET6 || + (current->s_context != 1 && sk->s_context != current->s_context)) continue; pos += LINE_LEN+1; if (pos <= offset) diff -NurP --minimal linux-2.4.23-pre4/net/socket.c linux-2.4.23-pre4-ctx17d/net/socket.c --- linux-2.4.23-pre4/net/socket.c 2003-08-25 20:32:26.000000000 +0200 +++ linux-2.4.23-pre4-ctx17d/net/socket.c 2003-09-13 17:19:02.000000000 +0200 @@ -1754,3 +1754,55 @@ len = 0; return len; } + +asmlinkage int sys_set_ipv4root ( + __u32 ip[], + int nbip, + __u32 bcast, + __u32 mask[]) +{ + int ret = -EPERM; + __u32 tbip[NB_IPV4ROOT]; + __u32 tbmask[NB_IPV4ROOT]; + struct iproot_info *ip_info = current->ip_info; + if (nbip < 0 || nbip > NB_IPV4ROOT) + ret = -EINVAL; + else if (copy_from_user(tbip,ip,nbip*sizeof(ip[0])) + || copy_from_user(tbmask,mask,nbip*sizeof(ip[0]))) + ret = -EFAULT; + else if (!ip_info + || ip_info->ipv4[0] == 0 + || capable(CAP_NET_ADMIN)) + // We are allowed to change everything + ret = 0; + else if (current->ip_info) + // We are allowed to select a subset of the currently + // installed IP numbers. No new one allowed + // We can't change the broadcast address though + int i; + int found = 0; + for (i=0; inbipv4; j++) { + if (ipi == ip_info->ipv4[j]) { + found++; + break; + } + } + } + if (found == nbip && bcast == ip_info->v4_bcast) { + ret = 0; + } + + } + if (ret == 0) { + sys_alloc_ip_info(); + current->ip_info->nbipv4 = nbip; + memcpy (current->ip_info->ipv4,tbip,nbip*sizeof(tbip[0])); + current->ip_info->v4_bcast = bcast; + memcpy (current->ip_info->mask,tbmask,nbip*sizeof(tbmask[0])); + } + return ret; +} + diff -NurP --minimal linux-2.4.23-pre4/net/unix/af_unix.c linux-2.4.23-pre4-ctx17d/net/unix/af_unix.c --- linux-2.4.23-pre4/net/unix/af_unix.c 2002-11-29 00:53:16.000000000 +0100 +++ linux-2.4.23-pre4-ctx17d/net/unix/af_unix.c 2003-09-13 15:24:22.000000000 +0200 @@ -479,6 +479,8 @@ sk->write_space = unix_write_space; + sk->s_context = current->s_context; + sk->max_ack_backlog = sysctl_unix_max_dgram_qlen; sk->destruct = unix_sock_destructor; sk->protinfo.af_unix.dentry=NULL; @@ -1756,6 +1758,9 @@ read_lock(&unix_table_lock); forall_unix_sockets (i,s) { + if (current->s_context != 1 && s->s_context != current->s_context) + continue; + unix_state_rlock(s); len+=sprintf(buffer+len,"%p: %08X %08X %08X %04X %02X %5lu",