struct context_info{
int refcount;
! short int s_context[NB_S_CONTEXT];/* root is allowed to switch the current */
! /* security context using any in this table */
char nodename[65];
char domainname[65];
***************
*** 305,308 ****
--- 308,322 ----
};
+ struct iproot_info{
+ int refcount;
+ int nbipv4;
+ __u32 ipv4[NB_IPV4ROOT];/* Process can only bind to these IPs */
+ /* The first one is used to connect */
+ /* and for bind any service */
+ /* The other must be used explicity when */
+ /* binding */
+ __u32 v4_bcast; /* Broadcast address used to receive UDP packets */
+ };
+
extern struct user_struct root_user;
***************
*** 434,440 ****
/* with the same s_context */
__u32 cap_bset; /* Maximum capability of this process and children */
- __u32 ipv4root; /* Process can only bind to this iP */
- __u32 ipv4root_bcast;
struct context_info *s_info;
void *notifier_data;
sigset_t *notifier_mask;
--- 448,453 ----
/* with the same s_context */
__u32 cap_bset; /* Maximum capability of this process and children */
struct context_info *s_info;
+ struct iproot_info *ip_info;
void *notifier_data;
sigset_t *notifier_mask;
***************
*** 970,973 ****
--- 983,989 ----
void sys_assign_s_info (struct task_struct *);
void sys_alloc_s_info (void);
+ void sys_release_ip_info (struct task_struct *);
+ void sys_assign_ip_info (struct task_struct *);
+ void sys_alloc_ip_info (void);
/* Not specified by any standard per-se, however it breaks too
diff -rc2P linux-2.4.18ctx-10/net/ipv4/devinet.c linux-2.4.18ctx-12/net/ipv4/devinet.c
*** linux-2.4.18ctx-10/net/ipv4/devinet.c Tue Feb 26 22:31:23 2002
--- linux-2.4.18ctx-12/net/ipv4/devinet.c Mon Jul 1 00:06:39 2002
***************
*** 456,459 ****
--- 456,485 ----
}
+ /*
+ 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 != 0 && info != NULL){
+ int i;
+ int nbip = info->nbipv4;
+ __u32 addr = ifa->ifa_local;
+ ret = 1;
+ for (i=0; i<nbip; i++){
+ if(info->ipv4[i] == addr){
+ ret = 0;
+ break;
+ }
+ }
+ }
+ return ret;
+ }
+
int devinet_ioctl(unsigned int cmd, void *arg)
***************
*** 560,566 ****
}
if (ifa != NULL
! && current->s_context != 0
! && current->ipv4root != 0
! && current->ipv4root != ifa->ifa_local){
ret = -EADDRNOTAVAIL;
goto done;
--- 586,590 ----
}
if (ifa != NULL
! && devinet_notiproot (ifa)){
ret = -EADDRNOTAVAIL;
goto done;
***************
*** 699,705 ****
for ( ; ifa; ifa = ifa->ifa_next) {
// We do not show other IP devices to vservers
! if (current->s_context != 0
! && current->ipv4root != 0
! && current->ipv4root != ifa->ifa_local) continue;
if (!buf) {
done += sizeof(ifr);
--- 723,727 ----
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);
***************
*** 919,925 ****
for (ifa = in_dev->ifa_list, ip_idx = 0; ifa;
ifa = ifa->ifa_next, ip_idx++) {
! if (current->s_context != 0
! && current->ipv4root != 0
! && current->ipv4root != ifa->ifa_local) continue;
if (ip_idx < s_ip_idx)
continue;
--- 941,945 ----
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;
diff -rc2P linux-2.4.18ctx-10/net/socket.c linux-2.4.18ctx-12/net/socket.c
*** linux-2.4.18ctx-10/net/socket.c Wed Apr 3 16:41:02 2002
--- linux-2.4.18ctx-12/net/socket.c Sun Jun 30 15:22:04 2002
***************
*** 1765,1776 ****
}
! asmlinkage int sys_set_ipv4root (__u32 ip, __u32 bcast)
{
int ret = -EPERM;
! if (current->ipv4root == 0
! || capable(CAP_SYS_ADMIN)){
ret = 0;
! current->ipv4root = ip;
! current->ipv4root_bcast = bcast;
}
return ret;
--- 1765,1808 ----
}
! asmlinkage int sys_set_ipv4root (__u32 ip[], int nbip, __u32 bcast)
{
int ret = -EPERM;
! __u32 tbip[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]))!=0){
! ret = -EFAULT;
! }else if (ip_info == NULL
! || ip_info->ipv4[0] == 0
! || capable(CAP_NET_ADMIN)){
! // We are allowed to change everything
ret = 0;
! }else if (current->ip_info != NULL){
! // 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; i<nbip; i++){
! int j;
! __u32 ipi = tbip[i];
! for (j=0; j<ip_info->nbipv4; 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;
}
return ret;