diff options
52 files changed, 368 insertions, 180 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 3a16d4fdaa05..498dc0d4ba5e 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
@@ -120,8 +120,8 @@ struct tun_sock; | |||
120 | struct tun_struct { | 120 | struct tun_struct { |
121 | struct tun_file *tfile; | 121 | struct tun_file *tfile; |
122 | unsigned int flags; | 122 | unsigned int flags; |
123 | uid_t owner; | 123 | kuid_t owner; |
124 | gid_t group; | 124 | kgid_t group; |
125 | 125 | ||
126 | struct net_device *dev; | 126 | struct net_device *dev; |
127 | netdev_features_t set_features; | 127 | netdev_features_t set_features; |
@@ -1031,8 +1031,8 @@ static void tun_setup(struct net_device *dev) | |||
1031 | { | 1031 | { |
1032 | struct tun_struct *tun = netdev_priv(dev); | 1032 | struct tun_struct *tun = netdev_priv(dev); |
1033 | 1033 | ||
1034 | tun->owner = -1; | 1034 | tun->owner = INVALID_UID; |
1035 | tun->group = -1; | 1035 | tun->group = INVALID_GID; |
1036 | 1036 | ||
1037 | dev->ethtool_ops = &tun_ethtool_ops; | 1037 | dev->ethtool_ops = &tun_ethtool_ops; |
1038 | dev->destructor = tun_free_netdev; | 1038 | dev->destructor = tun_free_netdev; |
@@ -1155,14 +1155,20 @@ static ssize_t tun_show_owner(struct device *dev, struct device_attribute *attr, | |||
1155 | char *buf) | 1155 | char *buf) |
1156 | { | 1156 | { |
1157 | struct tun_struct *tun = netdev_priv(to_net_dev(dev)); | 1157 | struct tun_struct *tun = netdev_priv(to_net_dev(dev)); |
1158 | return sprintf(buf, "%d\n", tun->owner); | 1158 | return uid_valid(tun->owner)? |
1159 | sprintf(buf, "%u\n", | ||
1160 | from_kuid_munged(current_user_ns(), tun->owner)): | ||
1161 | sprintf(buf, "-1\n"); | ||
1159 | } | 1162 | } |
1160 | 1163 | ||
1161 | static ssize_t tun_show_group(struct device *dev, struct device_attribute *attr, | 1164 | static ssize_t tun_show_group(struct device *dev, struct device_attribute *attr, |
1162 | char *buf) | 1165 | char *buf) |
1163 | { | 1166 | { |
1164 | struct tun_struct *tun = netdev_priv(to_net_dev(dev)); | 1167 | struct tun_struct *tun = netdev_priv(to_net_dev(dev)); |
1165 | return sprintf(buf, "%d\n", tun->group); | 1168 | return gid_valid(tun->group) ? |
1169 | sprintf(buf, "%u\n", | ||
1170 | from_kgid_munged(current_user_ns(), tun->group)): | ||
1171 | sprintf(buf, "-1\n"); | ||
1166 | } | 1172 | } |
1167 | 1173 | ||
1168 | static DEVICE_ATTR(tun_flags, 0444, tun_show_flags, NULL); | 1174 | static DEVICE_ATTR(tun_flags, 0444, tun_show_flags, NULL); |
@@ -1189,8 +1195,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) | |||
1189 | else | 1195 | else |
1190 | return -EINVAL; | 1196 | return -EINVAL; |
1191 | 1197 | ||
1192 | if (((tun->owner != -1 && cred->euid != tun->owner) || | 1198 | if (((uid_valid(tun->owner) && !uid_eq(cred->euid, tun->owner)) || |
1193 | (tun->group != -1 && !in_egroup_p(tun->group))) && | 1199 | (gid_valid(tun->group) && !in_egroup_p(tun->group))) && |
1194 | !capable(CAP_NET_ADMIN)) | 1200 | !capable(CAP_NET_ADMIN)) |
1195 | return -EPERM; | 1201 | return -EPERM; |
1196 | err = security_tun_dev_attach(tun->socket.sk); | 1202 | err = security_tun_dev_attach(tun->socket.sk); |
@@ -1374,6 +1380,8 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, | |||
1374 | void __user* argp = (void __user*)arg; | 1380 | void __user* argp = (void __user*)arg; |
1375 | struct sock_fprog fprog; | 1381 | struct sock_fprog fprog; |
1376 | struct ifreq ifr; | 1382 | struct ifreq ifr; |
1383 | kuid_t owner; | ||
1384 | kgid_t group; | ||
1377 | int sndbuf; | 1385 | int sndbuf; |
1378 | int vnet_hdr_sz; | 1386 | int vnet_hdr_sz; |
1379 | int ret; | 1387 | int ret; |
@@ -1447,16 +1455,26 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, | |||
1447 | 1455 | ||
1448 | case TUNSETOWNER: | 1456 | case TUNSETOWNER: |
1449 | /* Set owner of the device */ | 1457 | /* Set owner of the device */ |
1450 | tun->owner = (uid_t) arg; | 1458 | owner = make_kuid(current_user_ns(), arg); |
1451 | 1459 | if (!uid_valid(owner)) { | |
1452 | tun_debug(KERN_INFO, tun, "owner set to %d\n", tun->owner); | 1460 | ret = -EINVAL; |
1461 | break; | ||
1462 | } | ||
1463 | tun->owner = owner; | ||
1464 | tun_debug(KERN_INFO, tun, "owner set to %d\n", | ||
1465 | from_kuid(&init_user_ns, tun->owner)); | ||
1453 | break; | 1466 | break; |
1454 | 1467 | ||
1455 | case TUNSETGROUP: | 1468 | case TUNSETGROUP: |
1456 | /* Set group of the device */ | 1469 | /* Set group of the device */ |
1457 | tun->group= (gid_t) arg; | 1470 | group = make_kgid(current_user_ns(), arg); |
1458 | 1471 | if (!gid_valid(group)) { | |
1459 | tun_debug(KERN_INFO, tun, "group set to %d\n", tun->group); | 1472 | ret = -EINVAL; |
1473 | break; | ||
1474 | } | ||
1475 | tun->group = group; | ||
1476 | tun_debug(KERN_INFO, tun, "group set to %d\n", | ||
1477 | from_kgid(&init_user_ns, tun->group)); | ||
1460 | break; | 1478 | break; |
1461 | 1479 | ||
1462 | case TUNSETLINK: | 1480 | case TUNSETLINK: |
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index f9f15bb3f03a..c586f78c307f 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c | |||
@@ -232,8 +232,10 @@ static int adhoc; | |||
232 | 232 | ||
233 | static int probe = 1; | 233 | static int probe = 1; |
234 | 234 | ||
235 | static kuid_t proc_kuid; | ||
235 | static int proc_uid /* = 0 */; | 236 | static int proc_uid /* = 0 */; |
236 | 237 | ||
238 | static kgid_t proc_kgid; | ||
237 | static int proc_gid /* = 0 */; | 239 | static int proc_gid /* = 0 */; |
238 | 240 | ||
239 | static int airo_perm = 0555; | 241 | static int airo_perm = 0555; |
@@ -4499,78 +4501,79 @@ struct proc_data { | |||
4499 | static int setup_proc_entry( struct net_device *dev, | 4501 | static int setup_proc_entry( struct net_device *dev, |
4500 | struct airo_info *apriv ) { | 4502 | struct airo_info *apriv ) { |
4501 | struct proc_dir_entry *entry; | 4503 | struct proc_dir_entry *entry; |
4504 | |||
4502 | /* First setup the device directory */ | 4505 | /* First setup the device directory */ |
4503 | strcpy(apriv->proc_name,dev->name); | 4506 | strcpy(apriv->proc_name,dev->name); |
4504 | apriv->proc_entry = proc_mkdir_mode(apriv->proc_name, airo_perm, | 4507 | apriv->proc_entry = proc_mkdir_mode(apriv->proc_name, airo_perm, |
4505 | airo_entry); | 4508 | airo_entry); |
4506 | if (!apriv->proc_entry) | 4509 | if (!apriv->proc_entry) |
4507 | goto fail; | 4510 | goto fail; |
4508 | apriv->proc_entry->uid = proc_uid; | 4511 | apriv->proc_entry->uid = proc_kuid; |
4509 | apriv->proc_entry->gid = proc_gid; | 4512 | apriv->proc_entry->gid = proc_kgid; |
4510 | 4513 | ||
4511 | /* Setup the StatsDelta */ | 4514 | /* Setup the StatsDelta */ |
4512 | entry = proc_create_data("StatsDelta", S_IRUGO & proc_perm, | 4515 | entry = proc_create_data("StatsDelta", S_IRUGO & proc_perm, |
4513 | apriv->proc_entry, &proc_statsdelta_ops, dev); | 4516 | apriv->proc_entry, &proc_statsdelta_ops, dev); |
4514 | if (!entry) | 4517 | if (!entry) |
4515 | goto fail_stats_delta; | 4518 | goto fail_stats_delta; |
4516 | entry->uid = proc_uid; | 4519 | entry->uid = proc_kuid; |
4517 | entry->gid = proc_gid; | 4520 | entry->gid = proc_kgid; |
4518 | 4521 | ||
4519 | /* Setup the Stats */ | 4522 | /* Setup the Stats */ |
4520 | entry = proc_create_data("Stats", S_IRUGO & proc_perm, | 4523 | entry = proc_create_data("Stats", S_IRUGO & proc_perm, |
4521 | apriv->proc_entry, &proc_stats_ops, dev); | 4524 | apriv->proc_entry, &proc_stats_ops, dev); |
4522 | if (!entry) | 4525 | if (!entry) |
4523 | goto fail_stats; | 4526 | goto fail_stats; |
4524 | entry->uid = proc_uid; | 4527 | entry->uid = proc_kuid; |
4525 | entry->gid = proc_gid; | 4528 | entry->gid = proc_kgid; |
4526 | 4529 | ||
4527 | /* Setup the Status */ | 4530 | /* Setup the Status */ |
4528 | entry = proc_create_data("Status", S_IRUGO & proc_perm, | 4531 | entry = proc_create_data("Status", S_IRUGO & proc_perm, |
4529 | apriv->proc_entry, &proc_status_ops, dev); | 4532 | apriv->proc_entry, &proc_status_ops, dev); |
4530 | if (!entry) | 4533 | if (!entry) |
4531 | goto fail_status; | 4534 | goto fail_status; |
4532 | entry->uid = proc_uid; | 4535 | entry->uid = proc_kuid; |
4533 | entry->gid = proc_gid; | 4536 | entry->gid = proc_kgid; |
4534 | 4537 | ||
4535 | /* Setup the Config */ | 4538 | /* Setup the Config */ |
4536 | entry = proc_create_data("Config", proc_perm, | 4539 | entry = proc_create_data("Config", proc_perm, |
4537 | apriv->proc_entry, &proc_config_ops, dev); | 4540 | apriv->proc_entry, &proc_config_ops, dev); |
4538 | if (!entry) | 4541 | if (!entry) |
4539 | goto fail_config; | 4542 | goto fail_config; |
4540 | entry->uid = proc_uid; | 4543 | entry->uid = proc_kuid; |
4541 | entry->gid = proc_gid; | 4544 | entry->gid = proc_kgid; |
4542 | 4545 | ||
4543 | /* Setup the SSID */ | 4546 | /* Setup the SSID */ |
4544 | entry = proc_create_data("SSID", proc_perm, | 4547 | entry = proc_create_data("SSID", proc_perm, |
4545 | apriv->proc_entry, &proc_SSID_ops, dev); | 4548 | apriv->proc_entry, &proc_SSID_ops, dev); |
4546 | if (!entry) | 4549 | if (!entry) |
4547 | goto fail_ssid; | 4550 | goto fail_ssid; |
4548 | entry->uid = proc_uid; | 4551 | entry->uid = proc_kuid; |
4549 | entry->gid = proc_gid; | 4552 | entry->gid = proc_kgid; |
4550 | 4553 | ||
4551 | /* Setup the APList */ | 4554 | /* Setup the APList */ |
4552 | entry = proc_create_data("APList", proc_perm, | 4555 | entry = proc_create_data("APList", proc_perm, |
4553 | apriv->proc_entry, &proc_APList_ops, dev); | 4556 | apriv->proc_entry, &proc_APList_ops, dev); |
4554 | if (!entry) | 4557 | if (!entry) |
4555 | goto fail_aplist; | 4558 | goto fail_aplist; |
4556 | entry->uid = proc_uid; | 4559 | entry->uid = proc_kuid; |
4557 | entry->gid = proc_gid; | 4560 | entry->gid = proc_kgid; |
4558 | 4561 | ||
4559 | /* Setup the BSSList */ | 4562 | /* Setup the BSSList */ |
4560 | entry = proc_create_data("BSSList", proc_perm, | 4563 | entry = proc_create_data("BSSList", proc_perm, |
4561 | apriv->proc_entry, &proc_BSSList_ops, dev); | 4564 | apriv->proc_entry, &proc_BSSList_ops, dev); |
4562 | if (!entry) | 4565 | if (!entry) |
4563 | goto fail_bsslist; | 4566 | goto fail_bsslist; |
4564 | entry->uid = proc_uid; | 4567 | entry->uid = proc_kuid; |
4565 | entry->gid = proc_gid; | 4568 | entry->gid = proc_kgid; |
4566 | 4569 | ||
4567 | /* Setup the WepKey */ | 4570 | /* Setup the WepKey */ |
4568 | entry = proc_create_data("WepKey", proc_perm, | 4571 | entry = proc_create_data("WepKey", proc_perm, |
4569 | apriv->proc_entry, &proc_wepkey_ops, dev); | 4572 | apriv->proc_entry, &proc_wepkey_ops, dev); |
4570 | if (!entry) | 4573 | if (!entry) |
4571 | goto fail_wepkey; | 4574 | goto fail_wepkey; |
4572 | entry->uid = proc_uid; | 4575 | entry->uid = proc_kuid; |
4573 | entry->gid = proc_gid; | 4576 | entry->gid = proc_kgid; |
4574 | 4577 | ||
4575 | return 0; | 4578 | return 0; |
4576 | 4579 | ||
@@ -5697,11 +5700,16 @@ static int __init airo_init_module( void ) | |||
5697 | { | 5700 | { |
5698 | int i; | 5701 | int i; |
5699 | 5702 | ||
5703 | proc_kuid = make_kuid(&init_user_ns, proc_uid); | ||
5704 | proc_kgid = make_kgid(&init_user_ns, proc_gid); | ||
5705 | if (!uid_valid(proc_kuid) || !gid_valid(proc_kgid)) | ||
5706 | return -EINVAL; | ||
5707 | |||
5700 | airo_entry = proc_mkdir_mode("driver/aironet", airo_perm, NULL); | 5708 | airo_entry = proc_mkdir_mode("driver/aironet", airo_perm, NULL); |
5701 | 5709 | ||
5702 | if (airo_entry) { | 5710 | if (airo_entry) { |
5703 | airo_entry->uid = proc_uid; | 5711 | airo_entry->uid = proc_kuid; |
5704 | airo_entry->gid = proc_gid; | 5712 | airo_entry->gid = proc_kgid; |
5705 | } | 5713 | } |
5706 | 5714 | ||
5707 | for (i = 0; i < 4 && io[i] && irq[i]; i++) { | 5715 | for (i = 0; i < 4 && io[i] && irq[i]; i++) { |
diff --git a/fs/namei.c b/fs/namei.c index db76b866a097..51e9aa6e39dc 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -678,7 +678,7 @@ static inline int may_follow_link(struct path *link, struct nameidata *nd) | |||
678 | 678 | ||
679 | /* Allowed if owner and follower match. */ | 679 | /* Allowed if owner and follower match. */ |
680 | inode = link->dentry->d_inode; | 680 | inode = link->dentry->d_inode; |
681 | if (current_cred()->fsuid == inode->i_uid) | 681 | if (uid_eq(current_cred()->fsuid, inode->i_uid)) |
682 | return 0; | 682 | return 0; |
683 | 683 | ||
684 | /* Allowed if parent directory not sticky and world-writable. */ | 684 | /* Allowed if parent directory not sticky and world-writable. */ |
@@ -687,7 +687,7 @@ static inline int may_follow_link(struct path *link, struct nameidata *nd) | |||
687 | return 0; | 687 | return 0; |
688 | 688 | ||
689 | /* Allowed if parent directory and link owner match. */ | 689 | /* Allowed if parent directory and link owner match. */ |
690 | if (parent->i_uid == inode->i_uid) | 690 | if (uid_eq(parent->i_uid, inode->i_uid)) |
691 | return 0; | 691 | return 0; |
692 | 692 | ||
693 | path_put_conditional(link, nd); | 693 | path_put_conditional(link, nd); |
@@ -757,7 +757,7 @@ static int may_linkat(struct path *link) | |||
757 | /* Source inode owner (or CAP_FOWNER) can hardlink all they like, | 757 | /* Source inode owner (or CAP_FOWNER) can hardlink all they like, |
758 | * otherwise, it must be a safe source. | 758 | * otherwise, it must be a safe source. |
759 | */ | 759 | */ |
760 | if (cred->fsuid == inode->i_uid || safe_hardlink_source(inode) || | 760 | if (uid_eq(cred->fsuid, inode->i_uid) || safe_hardlink_source(inode) || |
761 | capable(CAP_FOWNER)) | 761 | capable(CAP_FOWNER)) |
762 | return 0; | 762 | return 0; |
763 | 763 | ||
diff --git a/fs/seq_file.c b/fs/seq_file.c index 14cf9de1dbe1..99dffab4c4e4 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/export.h> | 9 | #include <linux/export.h> |
10 | #include <linux/seq_file.h> | 10 | #include <linux/seq_file.h> |
11 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
12 | #include <linux/cred.h> | ||
12 | 13 | ||
13 | #include <asm/uaccess.h> | 14 | #include <asm/uaccess.h> |
14 | #include <asm/page.h> | 15 | #include <asm/page.h> |
@@ -56,6 +57,9 @@ int seq_open(struct file *file, const struct seq_operations *op) | |||
56 | memset(p, 0, sizeof(*p)); | 57 | memset(p, 0, sizeof(*p)); |
57 | mutex_init(&p->lock); | 58 | mutex_init(&p->lock); |
58 | p->op = op; | 59 | p->op = op; |
60 | #ifdef CONFIG_USER_NS | ||
61 | p->user_ns = file->f_cred->user_ns; | ||
62 | #endif | ||
59 | 63 | ||
60 | /* | 64 | /* |
61 | * Wrappers around seq_open(e.g. swaps_open) need to be | 65 | * Wrappers around seq_open(e.g. swaps_open) need to be |
diff --git a/include/linux/inet_diag.h b/include/linux/inet_diag.h index f1362b5447fc..e788c186ed3a 100644 --- a/include/linux/inet_diag.h +++ b/include/linux/inet_diag.h | |||
@@ -159,6 +159,7 @@ struct inet_diag_handler { | |||
159 | struct inet_connection_sock; | 159 | struct inet_connection_sock; |
160 | int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, | 160 | int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, |
161 | struct sk_buff *skb, struct inet_diag_req_v2 *req, | 161 | struct sk_buff *skb, struct inet_diag_req_v2 *req, |
162 | struct user_namespace *user_ns, | ||
162 | u32 pid, u32 seq, u16 nlmsg_flags, | 163 | u32 pid, u32 seq, u16 nlmsg_flags, |
163 | const struct nlmsghdr *unlh); | 164 | const struct nlmsghdr *unlh); |
164 | void inet_diag_dump_icsk(struct inet_hashinfo *h, struct sk_buff *skb, | 165 | void inet_diag_dump_icsk(struct inet_hashinfo *h, struct sk_buff *skb, |
diff --git a/include/linux/netlink.h b/include/linux/netlink.h index f74dd133788f..c9fdde2bc73f 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h | |||
@@ -165,6 +165,7 @@ struct netlink_skb_parms { | |||
165 | struct ucred creds; /* Skb credentials */ | 165 | struct ucred creds; /* Skb credentials */ |
166 | __u32 pid; | 166 | __u32 pid; |
167 | __u32 dst_group; | 167 | __u32 dst_group; |
168 | struct sock *ssk; | ||
168 | }; | 169 | }; |
169 | 170 | ||
170 | #define NETLINK_CB(skb) (*(struct netlink_skb_parms*)&((skb)->cb)) | 171 | #define NETLINK_CB(skb) (*(struct netlink_skb_parms*)&((skb)->cb)) |
diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h index 83c44eefe698..68a04a343cad 100644 --- a/include/linux/seq_file.h +++ b/include/linux/seq_file.h | |||
@@ -13,6 +13,7 @@ struct file; | |||
13 | struct path; | 13 | struct path; |
14 | struct inode; | 14 | struct inode; |
15 | struct dentry; | 15 | struct dentry; |
16 | struct user_namespace; | ||
16 | 17 | ||
17 | struct seq_file { | 18 | struct seq_file { |
18 | char *buf; | 19 | char *buf; |
@@ -25,6 +26,9 @@ struct seq_file { | |||
25 | struct mutex lock; | 26 | struct mutex lock; |
26 | const struct seq_operations *op; | 27 | const struct seq_operations *op; |
27 | int poll_event; | 28 | int poll_event; |
29 | #ifdef CONFIG_USER_NS | ||
30 | struct user_namespace *user_ns; | ||
31 | #endif | ||
28 | void *private; | 32 | void *private; |
29 | }; | 33 | }; |
30 | 34 | ||
@@ -128,6 +132,16 @@ int seq_put_decimal_ull(struct seq_file *m, char delimiter, | |||
128 | int seq_put_decimal_ll(struct seq_file *m, char delimiter, | 132 | int seq_put_decimal_ll(struct seq_file *m, char delimiter, |
129 | long long num); | 133 | long long num); |
130 | 134 | ||
135 | static inline struct user_namespace *seq_user_ns(struct seq_file *seq) | ||
136 | { | ||
137 | #ifdef CONFIG_USER_NS | ||
138 | return seq->user_ns; | ||
139 | #else | ||
140 | extern struct user_namespace init_user_ns; | ||
141 | return &init_user_ns; | ||
142 | #endif | ||
143 | } | ||
144 | |||
131 | #define SEQ_START_TOKEN ((void *)1) | 145 | #define SEQ_START_TOKEN ((void *)1) |
132 | /* | 146 | /* |
133 | * Helpers for iteration over list_head-s in seq_files | 147 | * Helpers for iteration over list_head-s in seq_files |
diff --git a/include/net/ax25.h b/include/net/ax25.h index 5d2352154cf6..53539acbd81a 100644 --- a/include/net/ax25.h +++ b/include/net/ax25.h | |||
@@ -157,7 +157,7 @@ enum { | |||
157 | typedef struct ax25_uid_assoc { | 157 | typedef struct ax25_uid_assoc { |
158 | struct hlist_node uid_node; | 158 | struct hlist_node uid_node; |
159 | atomic_t refcount; | 159 | atomic_t refcount; |
160 | uid_t uid; | 160 | kuid_t uid; |
161 | ax25_address call; | 161 | ax25_address call; |
162 | } ax25_uid_assoc; | 162 | } ax25_uid_assoc; |
163 | 163 | ||
@@ -434,7 +434,7 @@ extern unsigned long ax25_display_timer(struct timer_list *); | |||
434 | 434 | ||
435 | /* ax25_uid.c */ | 435 | /* ax25_uid.c */ |
436 | extern int ax25_uid_policy; | 436 | extern int ax25_uid_policy; |
437 | extern ax25_uid_assoc *ax25_findbyuid(uid_t); | 437 | extern ax25_uid_assoc *ax25_findbyuid(kuid_t); |
438 | extern int __must_check ax25_uid_ioctl(int, struct sockaddr_ax25 *); | 438 | extern int __must_check ax25_uid_ioctl(int, struct sockaddr_ax25 *); |
439 | extern const struct file_operations ax25_uid_fops; | 439 | extern const struct file_operations ax25_uid_fops; |
440 | extern void ax25_uid_free(void); | 440 | extern void ax25_uid_free(void); |
diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 6d01fb00ff2b..9bed5d483405 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h | |||
@@ -223,7 +223,10 @@ struct ip6_flowlabel { | |||
223 | struct ipv6_txoptions *opt; | 223 | struct ipv6_txoptions *opt; |
224 | unsigned long linger; | 224 | unsigned long linger; |
225 | u8 share; | 225 | u8 share; |
226 | u32 owner; | 226 | union { |
227 | struct pid *pid; | ||
228 | kuid_t uid; | ||
229 | } owner; | ||
227 | unsigned long lastuse; | 230 | unsigned long lastuse; |
228 | unsigned long expires; | 231 | unsigned long expires; |
229 | struct net *fl_net; | 232 | struct net *fl_net; |
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 1474dd65c66f..3516dc0cc615 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h | |||
@@ -5,6 +5,7 @@ | |||
5 | #ifndef __NETNS_IPV4_H__ | 5 | #ifndef __NETNS_IPV4_H__ |
6 | #define __NETNS_IPV4_H__ | 6 | #define __NETNS_IPV4_H__ |
7 | 7 | ||
8 | #include <linux/uidgid.h> | ||
8 | #include <net/inet_frag.h> | 9 | #include <net/inet_frag.h> |
9 | 10 | ||
10 | struct tcpm_hash_bucket; | 11 | struct tcpm_hash_bucket; |
@@ -62,7 +63,7 @@ struct netns_ipv4 { | |||
62 | int sysctl_icmp_ratemask; | 63 | int sysctl_icmp_ratemask; |
63 | int sysctl_icmp_errors_use_inbound_ifaddr; | 64 | int sysctl_icmp_errors_use_inbound_ifaddr; |
64 | 65 | ||
65 | unsigned int sysctl_ping_group_range[2]; | 66 | kgid_t sysctl_ping_group_range[2]; |
66 | long sysctl_tcp_mem[3]; | 67 | long sysctl_tcp_mem[3]; |
67 | 68 | ||
68 | atomic_t rt_genid; | 69 | atomic_t rt_genid; |
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index d9611e032418..4616f468d599 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h | |||
@@ -188,7 +188,8 @@ struct tcf_proto_ops { | |||
188 | 188 | ||
189 | unsigned long (*get)(struct tcf_proto*, u32 handle); | 189 | unsigned long (*get)(struct tcf_proto*, u32 handle); |
190 | void (*put)(struct tcf_proto*, unsigned long); | 190 | void (*put)(struct tcf_proto*, unsigned long); |
191 | int (*change)(struct tcf_proto*, unsigned long, | 191 | int (*change)(struct sk_buff *, |
192 | struct tcf_proto*, unsigned long, | ||
192 | u32 handle, struct nlattr **, | 193 | u32 handle, struct nlattr **, |
193 | unsigned long *); | 194 | unsigned long *); |
194 | int (*delete)(struct tcf_proto*, unsigned long); | 195 | int (*delete)(struct tcf_proto*, unsigned long); |
diff --git a/include/net/sock.h b/include/net/sock.h index 72132aef53fc..84bdaeca1314 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -606,6 +606,15 @@ static inline void sk_add_bind_node(struct sock *sk, | |||
606 | #define sk_for_each_bound(__sk, node, list) \ | 606 | #define sk_for_each_bound(__sk, node, list) \ |
607 | hlist_for_each_entry(__sk, node, list, sk_bind_node) | 607 | hlist_for_each_entry(__sk, node, list, sk_bind_node) |
608 | 608 | ||
609 | static inline struct user_namespace *sk_user_ns(struct sock *sk) | ||
610 | { | ||
611 | /* Careful only use this in a context where these parameters | ||
612 | * can not change and must all be valid, such as recvmsg from | ||
613 | * userspace. | ||
614 | */ | ||
615 | return sk->sk_socket->file->f_cred->user_ns; | ||
616 | } | ||
617 | |||
609 | /* Sock flags */ | 618 | /* Sock flags */ |
610 | enum sock_flags { | 619 | enum sock_flags { |
611 | SOCK_DEAD, | 620 | SOCK_DEAD, |
@@ -1670,7 +1679,7 @@ static inline void sock_graft(struct sock *sk, struct socket *parent) | |||
1670 | write_unlock_bh(&sk->sk_callback_lock); | 1679 | write_unlock_bh(&sk->sk_callback_lock); |
1671 | } | 1680 | } |
1672 | 1681 | ||
1673 | extern int sock_i_uid(struct sock *sk); | 1682 | extern kuid_t sock_i_uid(struct sock *sk); |
1674 | extern unsigned long sock_i_ino(struct sock *sk); | 1683 | extern unsigned long sock_i_ino(struct sock *sk); |
1675 | 1684 | ||
1676 | static inline struct dst_entry * | 1685 | static inline struct dst_entry * |
diff --git a/include/net/tcp.h b/include/net/tcp.h index 1f000ffe7075..9a0021d16d91 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
@@ -1510,7 +1510,8 @@ struct tcp_iter_state { | |||
1510 | sa_family_t family; | 1510 | sa_family_t family; |
1511 | enum tcp_seq_states state; | 1511 | enum tcp_seq_states state; |
1512 | struct sock *syn_wait_sk; | 1512 | struct sock *syn_wait_sk; |
1513 | int bucket, offset, sbucket, num, uid; | 1513 | int bucket, offset, sbucket, num; |
1514 | kuid_t uid; | ||
1514 | loff_t last_pos; | 1515 | loff_t last_pos; |
1515 | }; | 1516 | }; |
1516 | 1517 | ||
diff --git a/init/Kconfig b/init/Kconfig index af6c7f8ba019..b445d6f49bcf 100644 --- a/init/Kconfig +++ b/init/Kconfig | |||
@@ -942,28 +942,12 @@ config UIDGID_CONVERTED | |||
942 | depends on PROC_EVENTS = n | 942 | depends on PROC_EVENTS = n |
943 | 943 | ||
944 | # Networking | 944 | # Networking |
945 | depends on NET = n | ||
946 | depends on NET_9P = n | 945 | depends on NET_9P = n |
947 | depends on IPX = n | ||
948 | depends on PHONET = n | ||
949 | depends on NET_CLS_FLOW = n | ||
950 | depends on NETFILTER_XT_MATCH_OWNER = n | ||
951 | depends on NETFILTER_XT_MATCH_RECENT = n | ||
952 | depends on NETFILTER_XT_TARGET_LOG = n | ||
953 | depends on NETFILTER_NETLINK_LOG = n | ||
954 | depends on INET = n | ||
955 | depends on IPV6 = n | ||
956 | depends on IP_SCTP = n | ||
957 | depends on AF_RXRPC = n | 946 | depends on AF_RXRPC = n |
958 | depends on LLC2 = n | ||
959 | depends on NET_KEY = n | 947 | depends on NET_KEY = n |
960 | depends on INET_DIAG = n | ||
961 | depends on DNS_RESOLVER = n | 948 | depends on DNS_RESOLVER = n |
962 | depends on AX25 = n | ||
963 | depends on ATALK = n | ||
964 | 949 | ||
965 | # Filesystems | 950 | # Filesystems |
966 | depends on USB_DEVICEFS = n | ||
967 | depends on USB_GADGETFS = n | 951 | depends on USB_GADGETFS = n |
968 | depends on USB_FUNCTIONFS = n | 952 | depends on USB_FUNCTIONFS = n |
969 | depends on DEVTMPFS = n | 953 | depends on DEVTMPFS = n |
@@ -1019,9 +1003,6 @@ config UIDGID_CONVERTED | |||
1019 | depends on !UML || HOSTFS = n | 1003 | depends on !UML || HOSTFS = n |
1020 | 1004 | ||
1021 | # The rare drivers that won't build | 1005 | # The rare drivers that won't build |
1022 | depends on AIRO = n | ||
1023 | depends on AIRO_CS = n | ||
1024 | depends on TUN = n | ||
1025 | depends on INFINIBAND_QIB = n | 1006 | depends on INFINIBAND_QIB = n |
1026 | depends on BLK_DEV_LOOP = n | 1007 | depends on BLK_DEV_LOOP = n |
1027 | depends on ANDROID_BINDER_IPC = n | 1008 | depends on ANDROID_BINDER_IPC = n |
diff --git a/kernel/pid.c b/kernel/pid.c index e86b291ad834..aebd4f5aaf41 100644 --- a/kernel/pid.c +++ b/kernel/pid.c | |||
@@ -479,6 +479,7 @@ pid_t pid_nr_ns(struct pid *pid, struct pid_namespace *ns) | |||
479 | } | 479 | } |
480 | return nr; | 480 | return nr; |
481 | } | 481 | } |
482 | EXPORT_SYMBOL_GPL(pid_nr_ns); | ||
482 | 483 | ||
483 | pid_t pid_vnr(struct pid *pid) | 484 | pid_t pid_vnr(struct pid *pid) |
484 | { | 485 | { |
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c index b3c7fd554250..baa528d7dfbd 100644 --- a/kernel/pid_namespace.c +++ b/kernel/pid_namespace.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/proc_fs.h> | 17 | #include <linux/proc_fs.h> |
18 | #include <linux/reboot.h> | 18 | #include <linux/reboot.h> |
19 | #include <linux/export.h> | ||
19 | 20 | ||
20 | #define BITS_PER_PAGE (PAGE_SIZE*8) | 21 | #define BITS_PER_PAGE (PAGE_SIZE*8) |
21 | 22 | ||
@@ -144,6 +145,7 @@ void free_pid_ns(struct kref *kref) | |||
144 | if (parent != NULL) | 145 | if (parent != NULL) |
145 | put_pid_ns(parent); | 146 | put_pid_ns(parent); |
146 | } | 147 | } |
148 | EXPORT_SYMBOL_GPL(free_pid_ns); | ||
147 | 149 | ||
148 | void zap_pid_ns_processes(struct pid_namespace *pid_ns) | 150 | void zap_pid_ns_processes(struct pid_namespace *pid_ns) |
149 | { | 151 | { |
diff --git a/net/appletalk/atalk_proc.c b/net/appletalk/atalk_proc.c index b5b1a221c242..c30f3a0717fb 100644 --- a/net/appletalk/atalk_proc.c +++ b/net/appletalk/atalk_proc.c | |||
@@ -183,7 +183,8 @@ static int atalk_seq_socket_show(struct seq_file *seq, void *v) | |||
183 | ntohs(at->dest_net), at->dest_node, at->dest_port, | 183 | ntohs(at->dest_net), at->dest_node, at->dest_port, |
184 | sk_wmem_alloc_get(s), | 184 | sk_wmem_alloc_get(s), |
185 | sk_rmem_alloc_get(s), | 185 | sk_rmem_alloc_get(s), |
186 | s->sk_state, SOCK_INODE(s->sk_socket)->i_uid); | 186 | s->sk_state, |
187 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(s))); | ||
187 | out: | 188 | out: |
188 | return 0; | 189 | return 0; |
189 | } | 190 | } |
diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c index e3c579ba6325..957999e43ff7 100644 --- a/net/ax25/ax25_uid.c +++ b/net/ax25/ax25_uid.c | |||
@@ -51,14 +51,14 @@ int ax25_uid_policy; | |||
51 | 51 | ||
52 | EXPORT_SYMBOL(ax25_uid_policy); | 52 | EXPORT_SYMBOL(ax25_uid_policy); |
53 | 53 | ||
54 | ax25_uid_assoc *ax25_findbyuid(uid_t uid) | 54 | ax25_uid_assoc *ax25_findbyuid(kuid_t uid) |
55 | { | 55 | { |
56 | ax25_uid_assoc *ax25_uid, *res = NULL; | 56 | ax25_uid_assoc *ax25_uid, *res = NULL; |
57 | struct hlist_node *node; | 57 | struct hlist_node *node; |
58 | 58 | ||
59 | read_lock(&ax25_uid_lock); | 59 | read_lock(&ax25_uid_lock); |
60 | ax25_uid_for_each(ax25_uid, node, &ax25_uid_list) { | 60 | ax25_uid_for_each(ax25_uid, node, &ax25_uid_list) { |
61 | if (ax25_uid->uid == uid) { | 61 | if (uid_eq(ax25_uid->uid, uid)) { |
62 | ax25_uid_hold(ax25_uid); | 62 | ax25_uid_hold(ax25_uid); |
63 | res = ax25_uid; | 63 | res = ax25_uid; |
64 | break; | 64 | break; |
@@ -84,7 +84,7 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax) | |||
84 | read_lock(&ax25_uid_lock); | 84 | read_lock(&ax25_uid_lock); |
85 | ax25_uid_for_each(ax25_uid, node, &ax25_uid_list) { | 85 | ax25_uid_for_each(ax25_uid, node, &ax25_uid_list) { |
86 | if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0) { | 86 | if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0) { |
87 | res = ax25_uid->uid; | 87 | res = from_kuid_munged(current_user_ns(), ax25_uid->uid); |
88 | break; | 88 | break; |
89 | } | 89 | } |
90 | } | 90 | } |
@@ -93,9 +93,14 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax) | |||
93 | return res; | 93 | return res; |
94 | 94 | ||
95 | case SIOCAX25ADDUID: | 95 | case SIOCAX25ADDUID: |
96 | { | ||
97 | kuid_t sax25_kuid; | ||
96 | if (!capable(CAP_NET_ADMIN)) | 98 | if (!capable(CAP_NET_ADMIN)) |
97 | return -EPERM; | 99 | return -EPERM; |
98 | user = ax25_findbyuid(sax->sax25_uid); | 100 | sax25_kuid = make_kuid(current_user_ns(), sax->sax25_uid); |
101 | if (!uid_valid(sax25_kuid)) | ||
102 | return -EINVAL; | ||
103 | user = ax25_findbyuid(sax25_kuid); | ||
99 | if (user) { | 104 | if (user) { |
100 | ax25_uid_put(user); | 105 | ax25_uid_put(user); |
101 | return -EEXIST; | 106 | return -EEXIST; |
@@ -106,7 +111,7 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax) | |||
106 | return -ENOMEM; | 111 | return -ENOMEM; |
107 | 112 | ||
108 | atomic_set(&ax25_uid->refcount, 1); | 113 | atomic_set(&ax25_uid->refcount, 1); |
109 | ax25_uid->uid = sax->sax25_uid; | 114 | ax25_uid->uid = sax25_kuid; |
110 | ax25_uid->call = sax->sax25_call; | 115 | ax25_uid->call = sax->sax25_call; |
111 | 116 | ||
112 | write_lock(&ax25_uid_lock); | 117 | write_lock(&ax25_uid_lock); |
@@ -114,7 +119,7 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax) | |||
114 | write_unlock(&ax25_uid_lock); | 119 | write_unlock(&ax25_uid_lock); |
115 | 120 | ||
116 | return 0; | 121 | return 0; |
117 | 122 | } | |
118 | case SIOCAX25DELUID: | 123 | case SIOCAX25DELUID: |
119 | if (!capable(CAP_NET_ADMIN)) | 124 | if (!capable(CAP_NET_ADMIN)) |
120 | return -EPERM; | 125 | return -EPERM; |
@@ -172,7 +177,9 @@ static int ax25_uid_seq_show(struct seq_file *seq, void *v) | |||
172 | struct ax25_uid_assoc *pt; | 177 | struct ax25_uid_assoc *pt; |
173 | 178 | ||
174 | pt = hlist_entry(v, struct ax25_uid_assoc, uid_node); | 179 | pt = hlist_entry(v, struct ax25_uid_assoc, uid_node); |
175 | seq_printf(seq, "%6d %s\n", pt->uid, ax2asc(buf, &pt->call)); | 180 | seq_printf(seq, "%6d %s\n", |
181 | from_kuid_munged(seq_user_ns(seq), pt->uid), | ||
182 | ax2asc(buf, &pt->call)); | ||
176 | } | 183 | } |
177 | return 0; | 184 | return 0; |
178 | } | 185 | } |
diff --git a/net/core/dev.c b/net/core/dev.c index 2f25d0cac51c..3401e2dab7cc 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -4520,8 +4520,8 @@ static void dev_change_rx_flags(struct net_device *dev, int flags) | |||
4520 | static int __dev_set_promiscuity(struct net_device *dev, int inc) | 4520 | static int __dev_set_promiscuity(struct net_device *dev, int inc) |
4521 | { | 4521 | { |
4522 | unsigned int old_flags = dev->flags; | 4522 | unsigned int old_flags = dev->flags; |
4523 | uid_t uid; | 4523 | kuid_t uid; |
4524 | gid_t gid; | 4524 | kgid_t gid; |
4525 | 4525 | ||
4526 | ASSERT_RTNL(); | 4526 | ASSERT_RTNL(); |
4527 | 4527 | ||
@@ -4553,7 +4553,8 @@ static int __dev_set_promiscuity(struct net_device *dev, int inc) | |||
4553 | dev->name, (dev->flags & IFF_PROMISC), | 4553 | dev->name, (dev->flags & IFF_PROMISC), |
4554 | (old_flags & IFF_PROMISC), | 4554 | (old_flags & IFF_PROMISC), |
4555 | audit_get_loginuid(current), | 4555 | audit_get_loginuid(current), |
4556 | uid, gid, | 4556 | from_kuid(&init_user_ns, uid), |
4557 | from_kgid(&init_user_ns, gid), | ||
4557 | audit_get_sessionid(current)); | 4558 | audit_get_sessionid(current)); |
4558 | } | 4559 | } |
4559 | 4560 | ||
diff --git a/net/core/scm.c b/net/core/scm.c index 040cebeed45b..6ab491d6c26f 100644 --- a/net/core/scm.c +++ b/net/core/scm.c | |||
@@ -45,12 +45,17 @@ | |||
45 | static __inline__ int scm_check_creds(struct ucred *creds) | 45 | static __inline__ int scm_check_creds(struct ucred *creds) |
46 | { | 46 | { |
47 | const struct cred *cred = current_cred(); | 47 | const struct cred *cred = current_cred(); |
48 | kuid_t uid = make_kuid(cred->user_ns, creds->uid); | ||
49 | kgid_t gid = make_kgid(cred->user_ns, creds->gid); | ||
50 | |||
51 | if (!uid_valid(uid) || !gid_valid(gid)) | ||
52 | return -EINVAL; | ||
48 | 53 | ||
49 | if ((creds->pid == task_tgid_vnr(current) || capable(CAP_SYS_ADMIN)) && | 54 | if ((creds->pid == task_tgid_vnr(current) || capable(CAP_SYS_ADMIN)) && |
50 | ((creds->uid == cred->uid || creds->uid == cred->euid || | 55 | ((uid_eq(uid, cred->uid) || uid_eq(uid, cred->euid) || |
51 | creds->uid == cred->suid) || capable(CAP_SETUID)) && | 56 | uid_eq(uid, cred->suid)) || capable(CAP_SETUID)) && |
52 | ((creds->gid == cred->gid || creds->gid == cred->egid || | 57 | ((gid_eq(gid, cred->gid) || gid_eq(gid, cred->egid) || |
53 | creds->gid == cred->sgid) || capable(CAP_SETGID))) { | 58 | gid_eq(gid, cred->sgid)) || capable(CAP_SETGID))) { |
54 | return 0; | 59 | return 0; |
55 | } | 60 | } |
56 | return -EPERM; | 61 | return -EPERM; |
@@ -149,6 +154,9 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p) | |||
149 | goto error; | 154 | goto error; |
150 | break; | 155 | break; |
151 | case SCM_CREDENTIALS: | 156 | case SCM_CREDENTIALS: |
157 | { | ||
158 | kuid_t uid; | ||
159 | kgid_t gid; | ||
152 | if (cmsg->cmsg_len != CMSG_LEN(sizeof(struct ucred))) | 160 | if (cmsg->cmsg_len != CMSG_LEN(sizeof(struct ucred))) |
153 | goto error; | 161 | goto error; |
154 | memcpy(&p->creds, CMSG_DATA(cmsg), sizeof(struct ucred)); | 162 | memcpy(&p->creds, CMSG_DATA(cmsg), sizeof(struct ucred)); |
@@ -166,22 +174,29 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p) | |||
166 | p->pid = pid; | 174 | p->pid = pid; |
167 | } | 175 | } |
168 | 176 | ||
177 | err = -EINVAL; | ||
178 | uid = make_kuid(current_user_ns(), p->creds.uid); | ||
179 | gid = make_kgid(current_user_ns(), p->creds.gid); | ||
180 | if (!uid_valid(uid) || !gid_valid(gid)) | ||
181 | goto error; | ||
182 | |||
169 | if (!p->cred || | 183 | if (!p->cred || |
170 | (p->cred->euid != p->creds.uid) || | 184 | !uid_eq(p->cred->euid, uid) || |
171 | (p->cred->egid != p->creds.gid)) { | 185 | !gid_eq(p->cred->egid, gid)) { |
172 | struct cred *cred; | 186 | struct cred *cred; |
173 | err = -ENOMEM; | 187 | err = -ENOMEM; |
174 | cred = prepare_creds(); | 188 | cred = prepare_creds(); |
175 | if (!cred) | 189 | if (!cred) |
176 | goto error; | 190 | goto error; |
177 | 191 | ||
178 | cred->uid = cred->euid = p->creds.uid; | 192 | cred->uid = cred->euid = uid; |
179 | cred->gid = cred->egid = p->creds.gid; | 193 | cred->gid = cred->egid = gid; |
180 | if (p->cred) | 194 | if (p->cred) |
181 | put_cred(p->cred); | 195 | put_cred(p->cred); |
182 | p->cred = cred; | 196 | p->cred = cred; |
183 | } | 197 | } |
184 | break; | 198 | break; |
199 | } | ||
185 | default: | 200 | default: |
186 | goto error; | 201 | goto error; |
187 | } | 202 | } |
diff --git a/net/core/sock.c b/net/core/sock.c index 116786c55fe9..d765156eab65 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -868,8 +868,8 @@ void cred_to_ucred(struct pid *pid, const struct cred *cred, | |||
868 | if (cred) { | 868 | if (cred) { |
869 | struct user_namespace *current_ns = current_user_ns(); | 869 | struct user_namespace *current_ns = current_user_ns(); |
870 | 870 | ||
871 | ucred->uid = from_kuid(current_ns, cred->euid); | 871 | ucred->uid = from_kuid_munged(current_ns, cred->euid); |
872 | ucred->gid = from_kgid(current_ns, cred->egid); | 872 | ucred->gid = from_kgid_munged(current_ns, cred->egid); |
873 | } | 873 | } |
874 | } | 874 | } |
875 | EXPORT_SYMBOL_GPL(cred_to_ucred); | 875 | EXPORT_SYMBOL_GPL(cred_to_ucred); |
@@ -1527,12 +1527,12 @@ void sock_edemux(struct sk_buff *skb) | |||
1527 | } | 1527 | } |
1528 | EXPORT_SYMBOL(sock_edemux); | 1528 | EXPORT_SYMBOL(sock_edemux); |
1529 | 1529 | ||
1530 | int sock_i_uid(struct sock *sk) | 1530 | kuid_t sock_i_uid(struct sock *sk) |
1531 | { | 1531 | { |
1532 | int uid; | 1532 | kuid_t uid; |
1533 | 1533 | ||
1534 | read_lock_bh(&sk->sk_callback_lock); | 1534 | read_lock_bh(&sk->sk_callback_lock); |
1535 | uid = sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_uid : 0; | 1535 | uid = sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_uid : GLOBAL_ROOT_UID; |
1536 | read_unlock_bh(&sk->sk_callback_lock); | 1536 | read_unlock_bh(&sk->sk_callback_lock); |
1537 | return uid; | 1537 | return uid; |
1538 | } | 1538 | } |
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 570e61f9611f..8bc005b1435f 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c | |||
@@ -69,6 +69,7 @@ static inline void inet_diag_unlock_handler( | |||
69 | 69 | ||
70 | int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, | 70 | int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, |
71 | struct sk_buff *skb, struct inet_diag_req_v2 *req, | 71 | struct sk_buff *skb, struct inet_diag_req_v2 *req, |
72 | struct user_namespace *user_ns, | ||
72 | u32 pid, u32 seq, u16 nlmsg_flags, | 73 | u32 pid, u32 seq, u16 nlmsg_flags, |
73 | const struct nlmsghdr *unlh) | 74 | const struct nlmsghdr *unlh) |
74 | { | 75 | { |
@@ -124,7 +125,7 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, | |||
124 | } | 125 | } |
125 | #endif | 126 | #endif |
126 | 127 | ||
127 | r->idiag_uid = sock_i_uid(sk); | 128 | r->idiag_uid = from_kuid_munged(user_ns, sock_i_uid(sk)); |
128 | r->idiag_inode = sock_i_ino(sk); | 129 | r->idiag_inode = sock_i_ino(sk); |
129 | 130 | ||
130 | if (ext & (1 << (INET_DIAG_MEMINFO - 1))) { | 131 | if (ext & (1 << (INET_DIAG_MEMINFO - 1))) { |
@@ -199,11 +200,12 @@ EXPORT_SYMBOL_GPL(inet_sk_diag_fill); | |||
199 | 200 | ||
200 | static int inet_csk_diag_fill(struct sock *sk, | 201 | static int inet_csk_diag_fill(struct sock *sk, |
201 | struct sk_buff *skb, struct inet_diag_req_v2 *req, | 202 | struct sk_buff *skb, struct inet_diag_req_v2 *req, |
203 | struct user_namespace *user_ns, | ||
202 | u32 pid, u32 seq, u16 nlmsg_flags, | 204 | u32 pid, u32 seq, u16 nlmsg_flags, |
203 | const struct nlmsghdr *unlh) | 205 | const struct nlmsghdr *unlh) |
204 | { | 206 | { |
205 | return inet_sk_diag_fill(sk, inet_csk(sk), | 207 | return inet_sk_diag_fill(sk, inet_csk(sk), |
206 | skb, req, pid, seq, nlmsg_flags, unlh); | 208 | skb, req, user_ns, pid, seq, nlmsg_flags, unlh); |
207 | } | 209 | } |
208 | 210 | ||
209 | static int inet_twsk_diag_fill(struct inet_timewait_sock *tw, | 211 | static int inet_twsk_diag_fill(struct inet_timewait_sock *tw, |
@@ -256,14 +258,16 @@ static int inet_twsk_diag_fill(struct inet_timewait_sock *tw, | |||
256 | } | 258 | } |
257 | 259 | ||
258 | static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, | 260 | static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, |
259 | struct inet_diag_req_v2 *r, u32 pid, u32 seq, u16 nlmsg_flags, | 261 | struct inet_diag_req_v2 *r, |
262 | struct user_namespace *user_ns, | ||
263 | u32 pid, u32 seq, u16 nlmsg_flags, | ||
260 | const struct nlmsghdr *unlh) | 264 | const struct nlmsghdr *unlh) |
261 | { | 265 | { |
262 | if (sk->sk_state == TCP_TIME_WAIT) | 266 | if (sk->sk_state == TCP_TIME_WAIT) |
263 | return inet_twsk_diag_fill((struct inet_timewait_sock *)sk, | 267 | return inet_twsk_diag_fill((struct inet_timewait_sock *)sk, |
264 | skb, r, pid, seq, nlmsg_flags, | 268 | skb, r, pid, seq, nlmsg_flags, |
265 | unlh); | 269 | unlh); |
266 | return inet_csk_diag_fill(sk, skb, r, pid, seq, nlmsg_flags, unlh); | 270 | return inet_csk_diag_fill(sk, skb, r, user_ns, pid, seq, nlmsg_flags, unlh); |
267 | } | 271 | } |
268 | 272 | ||
269 | int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_skb, | 273 | int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_skb, |
@@ -311,6 +315,7 @@ int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_s | |||
311 | } | 315 | } |
312 | 316 | ||
313 | err = sk_diag_fill(sk, rep, req, | 317 | err = sk_diag_fill(sk, rep, req, |
318 | sk_user_ns(NETLINK_CB(in_skb).ssk), | ||
314 | NETLINK_CB(in_skb).pid, | 319 | NETLINK_CB(in_skb).pid, |
315 | nlh->nlmsg_seq, 0, nlh); | 320 | nlh->nlmsg_seq, 0, nlh); |
316 | if (err < 0) { | 321 | if (err < 0) { |
@@ -551,6 +556,7 @@ static int inet_csk_diag_dump(struct sock *sk, | |||
551 | return 0; | 556 | return 0; |
552 | 557 | ||
553 | return inet_csk_diag_fill(sk, skb, r, | 558 | return inet_csk_diag_fill(sk, skb, r, |
559 | sk_user_ns(NETLINK_CB(cb->skb).ssk), | ||
554 | NETLINK_CB(cb->skb).pid, | 560 | NETLINK_CB(cb->skb).pid, |
555 | cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); | 561 | cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); |
556 | } | 562 | } |
@@ -591,7 +597,9 @@ static int inet_twsk_diag_dump(struct inet_timewait_sock *tw, | |||
591 | } | 597 | } |
592 | 598 | ||
593 | static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk, | 599 | static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk, |
594 | struct request_sock *req, u32 pid, u32 seq, | 600 | struct request_sock *req, |
601 | struct user_namespace *user_ns, | ||
602 | u32 pid, u32 seq, | ||
595 | const struct nlmsghdr *unlh) | 603 | const struct nlmsghdr *unlh) |
596 | { | 604 | { |
597 | const struct inet_request_sock *ireq = inet_rsk(req); | 605 | const struct inet_request_sock *ireq = inet_rsk(req); |
@@ -625,7 +633,7 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk, | |||
625 | r->idiag_expires = jiffies_to_msecs(tmo); | 633 | r->idiag_expires = jiffies_to_msecs(tmo); |
626 | r->idiag_rqueue = 0; | 634 | r->idiag_rqueue = 0; |
627 | r->idiag_wqueue = 0; | 635 | r->idiag_wqueue = 0; |
628 | r->idiag_uid = sock_i_uid(sk); | 636 | r->idiag_uid = from_kuid_munged(user_ns, sock_i_uid(sk)); |
629 | r->idiag_inode = 0; | 637 | r->idiag_inode = 0; |
630 | #if IS_ENABLED(CONFIG_IPV6) | 638 | #if IS_ENABLED(CONFIG_IPV6) |
631 | if (r->idiag_family == AF_INET6) { | 639 | if (r->idiag_family == AF_INET6) { |
@@ -702,6 +710,7 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk, | |||
702 | } | 710 | } |
703 | 711 | ||
704 | err = inet_diag_fill_req(skb, sk, req, | 712 | err = inet_diag_fill_req(skb, sk, req, |
713 | sk_user_ns(NETLINK_CB(cb->skb).ssk), | ||
705 | NETLINK_CB(cb->skb).pid, | 714 | NETLINK_CB(cb->skb).pid, |
706 | cb->nlh->nlmsg_seq, cb->nlh); | 715 | cb->nlh->nlmsg_seq, cb->nlh); |
707 | if (err < 0) { | 716 | if (err < 0) { |
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 6232d476f37e..8f3d05424a3e 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c | |||
@@ -185,10 +185,10 @@ exit: | |||
185 | return sk; | 185 | return sk; |
186 | } | 186 | } |
187 | 187 | ||
188 | static void inet_get_ping_group_range_net(struct net *net, gid_t *low, | 188 | static void inet_get_ping_group_range_net(struct net *net, kgid_t *low, |
189 | gid_t *high) | 189 | kgid_t *high) |
190 | { | 190 | { |
191 | gid_t *data = net->ipv4.sysctl_ping_group_range; | 191 | kgid_t *data = net->ipv4.sysctl_ping_group_range; |
192 | unsigned int seq; | 192 | unsigned int seq; |
193 | 193 | ||
194 | do { | 194 | do { |
@@ -203,19 +203,13 @@ static void inet_get_ping_group_range_net(struct net *net, gid_t *low, | |||
203 | static int ping_init_sock(struct sock *sk) | 203 | static int ping_init_sock(struct sock *sk) |
204 | { | 204 | { |
205 | struct net *net = sock_net(sk); | 205 | struct net *net = sock_net(sk); |
206 | gid_t group = current_egid(); | 206 | kgid_t group = current_egid(); |
207 | gid_t range[2]; | ||
208 | struct group_info *group_info = get_current_groups(); | 207 | struct group_info *group_info = get_current_groups(); |
209 | int i, j, count = group_info->ngroups; | 208 | int i, j, count = group_info->ngroups; |
210 | kgid_t low, high; | 209 | kgid_t low, high; |
211 | 210 | ||
212 | inet_get_ping_group_range_net(net, range, range+1); | 211 | inet_get_ping_group_range_net(net, &low, &high); |
213 | low = make_kgid(&init_user_ns, range[0]); | 212 | if (gid_lte(low, group) && gid_lte(group, high)) |
214 | high = make_kgid(&init_user_ns, range[1]); | ||
215 | if (!gid_valid(low) || !gid_valid(high) || gid_lt(high, low)) | ||
216 | return -EACCES; | ||
217 | |||
218 | if (range[0] <= group && group <= range[1]) | ||
219 | return 0; | 213 | return 0; |
220 | 214 | ||
221 | for (i = 0; i < group_info->nblocks; i++) { | 215 | for (i = 0; i < group_info->nblocks; i++) { |
@@ -845,7 +839,9 @@ static void ping_format_sock(struct sock *sp, struct seq_file *f, | |||
845 | bucket, src, srcp, dest, destp, sp->sk_state, | 839 | bucket, src, srcp, dest, destp, sp->sk_state, |
846 | sk_wmem_alloc_get(sp), | 840 | sk_wmem_alloc_get(sp), |
847 | sk_rmem_alloc_get(sp), | 841 | sk_rmem_alloc_get(sp), |
848 | 0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp), | 842 | 0, 0L, 0, |
843 | from_kuid_munged(seq_user_ns(f), sock_i_uid(sp)), | ||
844 | 0, sock_i_ino(sp), | ||
849 | atomic_read(&sp->sk_refcnt), sp, | 845 | atomic_read(&sp->sk_refcnt), sp, |
850 | atomic_read(&sp->sk_drops), len); | 846 | atomic_read(&sp->sk_drops), len); |
851 | } | 847 | } |
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index ff0f071969ea..f2425785d40a 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
@@ -992,7 +992,9 @@ static void raw_sock_seq_show(struct seq_file *seq, struct sock *sp, int i) | |||
992 | i, src, srcp, dest, destp, sp->sk_state, | 992 | i, src, srcp, dest, destp, sp->sk_state, |
993 | sk_wmem_alloc_get(sp), | 993 | sk_wmem_alloc_get(sp), |
994 | sk_rmem_alloc_get(sp), | 994 | sk_rmem_alloc_get(sp), |
995 | 0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp), | 995 | 0, 0L, 0, |
996 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)), | ||
997 | 0, sock_i_ino(sp), | ||
996 | atomic_read(&sp->sk_refcnt), sp, atomic_read(&sp->sk_drops)); | 998 | atomic_read(&sp->sk_refcnt), sp, atomic_read(&sp->sk_drops)); |
997 | } | 999 | } |
998 | 1000 | ||
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 1b5ce96707a3..3e78c79b5586 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c | |||
@@ -76,9 +76,9 @@ static int ipv4_local_port_range(ctl_table *table, int write, | |||
76 | } | 76 | } |
77 | 77 | ||
78 | 78 | ||
79 | static void inet_get_ping_group_range_table(struct ctl_table *table, gid_t *low, gid_t *high) | 79 | static void inet_get_ping_group_range_table(struct ctl_table *table, kgid_t *low, kgid_t *high) |
80 | { | 80 | { |
81 | gid_t *data = table->data; | 81 | kgid_t *data = table->data; |
82 | unsigned int seq; | 82 | unsigned int seq; |
83 | do { | 83 | do { |
84 | seq = read_seqbegin(&sysctl_local_ports.lock); | 84 | seq = read_seqbegin(&sysctl_local_ports.lock); |
@@ -89,12 +89,12 @@ static void inet_get_ping_group_range_table(struct ctl_table *table, gid_t *low, | |||
89 | } | 89 | } |
90 | 90 | ||
91 | /* Update system visible IP port range */ | 91 | /* Update system visible IP port range */ |
92 | static void set_ping_group_range(struct ctl_table *table, gid_t range[2]) | 92 | static void set_ping_group_range(struct ctl_table *table, kgid_t low, kgid_t high) |
93 | { | 93 | { |
94 | gid_t *data = table->data; | 94 | kgid_t *data = table->data; |
95 | write_seqlock(&sysctl_local_ports.lock); | 95 | write_seqlock(&sysctl_local_ports.lock); |
96 | data[0] = range[0]; | 96 | data[0] = low; |
97 | data[1] = range[1]; | 97 | data[1] = high; |
98 | write_sequnlock(&sysctl_local_ports.lock); | 98 | write_sequnlock(&sysctl_local_ports.lock); |
99 | } | 99 | } |
100 | 100 | ||
@@ -103,21 +103,33 @@ static int ipv4_ping_group_range(ctl_table *table, int write, | |||
103 | void __user *buffer, | 103 | void __user *buffer, |
104 | size_t *lenp, loff_t *ppos) | 104 | size_t *lenp, loff_t *ppos) |
105 | { | 105 | { |
106 | struct user_namespace *user_ns = current_user_ns(); | ||
106 | int ret; | 107 | int ret; |
107 | gid_t range[2]; | 108 | gid_t urange[2]; |
109 | kgid_t low, high; | ||
108 | ctl_table tmp = { | 110 | ctl_table tmp = { |
109 | .data = &range, | 111 | .data = &urange, |
110 | .maxlen = sizeof(range), | 112 | .maxlen = sizeof(urange), |
111 | .mode = table->mode, | 113 | .mode = table->mode, |
112 | .extra1 = &ip_ping_group_range_min, | 114 | .extra1 = &ip_ping_group_range_min, |
113 | .extra2 = &ip_ping_group_range_max, | 115 | .extra2 = &ip_ping_group_range_max, |
114 | }; | 116 | }; |
115 | 117 | ||
116 | inet_get_ping_group_range_table(table, range, range + 1); | 118 | inet_get_ping_group_range_table(table, &low, &high); |
119 | urange[0] = from_kgid_munged(user_ns, low); | ||
120 | urange[1] = from_kgid_munged(user_ns, high); | ||
117 | ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos); | 121 | ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos); |
118 | 122 | ||
119 | if (write && ret == 0) | 123 | if (write && ret == 0) { |
120 | set_ping_group_range(table, range); | 124 | low = make_kgid(user_ns, urange[0]); |
125 | high = make_kgid(user_ns, urange[1]); | ||
126 | if (!gid_valid(low) || !gid_valid(high) || | ||
127 | (urange[1] < urange[0]) || gid_lt(high, low)) { | ||
128 | low = make_kgid(&init_user_ns, 1); | ||
129 | high = make_kgid(&init_user_ns, 0); | ||
130 | } | ||
131 | set_ping_group_range(table, low, high); | ||
132 | } | ||
121 | 133 | ||
122 | return ret; | 134 | return ret; |
123 | } | 135 | } |
@@ -786,7 +798,7 @@ static struct ctl_table ipv4_net_table[] = { | |||
786 | { | 798 | { |
787 | .procname = "ping_group_range", | 799 | .procname = "ping_group_range", |
788 | .data = &init_net.ipv4.sysctl_ping_group_range, | 800 | .data = &init_net.ipv4.sysctl_ping_group_range, |
789 | .maxlen = sizeof(init_net.ipv4.sysctl_ping_group_range), | 801 | .maxlen = sizeof(gid_t)*2, |
790 | .mode = 0644, | 802 | .mode = 0644, |
791 | .proc_handler = ipv4_ping_group_range, | 803 | .proc_handler = ipv4_ping_group_range, |
792 | }, | 804 | }, |
@@ -830,8 +842,8 @@ static __net_init int ipv4_sysctl_init_net(struct net *net) | |||
830 | * Sane defaults - nobody may create ping sockets. | 842 | * Sane defaults - nobody may create ping sockets. |
831 | * Boot scripts should set this to distro-specific group. | 843 | * Boot scripts should set this to distro-specific group. |
832 | */ | 844 | */ |
833 | net->ipv4.sysctl_ping_group_range[0] = 1; | 845 | net->ipv4.sysctl_ping_group_range[0] = make_kgid(&init_user_ns, 1); |
834 | net->ipv4.sysctl_ping_group_range[1] = 0; | 846 | net->ipv4.sysctl_ping_group_range[1] = make_kgid(&init_user_ns, 0); |
835 | 847 | ||
836 | tcp_init_mem(net); | 848 | tcp_init_mem(net); |
837 | 849 | ||
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 1e15c5be04e7..36f02f954ac1 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -2393,7 +2393,7 @@ void tcp_proc_unregister(struct net *net, struct tcp_seq_afinfo *afinfo) | |||
2393 | EXPORT_SYMBOL(tcp_proc_unregister); | 2393 | EXPORT_SYMBOL(tcp_proc_unregister); |
2394 | 2394 | ||
2395 | static void get_openreq4(const struct sock *sk, const struct request_sock *req, | 2395 | static void get_openreq4(const struct sock *sk, const struct request_sock *req, |
2396 | struct seq_file *f, int i, int uid, int *len) | 2396 | struct seq_file *f, int i, kuid_t uid, int *len) |
2397 | { | 2397 | { |
2398 | const struct inet_request_sock *ireq = inet_rsk(req); | 2398 | const struct inet_request_sock *ireq = inet_rsk(req); |
2399 | long delta = req->expires - jiffies; | 2399 | long delta = req->expires - jiffies; |
@@ -2410,7 +2410,7 @@ static void get_openreq4(const struct sock *sk, const struct request_sock *req, | |||
2410 | 1, /* timers active (only the expire timer) */ | 2410 | 1, /* timers active (only the expire timer) */ |
2411 | jiffies_delta_to_clock_t(delta), | 2411 | jiffies_delta_to_clock_t(delta), |
2412 | req->retrans, | 2412 | req->retrans, |
2413 | uid, | 2413 | from_kuid_munged(seq_user_ns(f), uid), |
2414 | 0, /* non standard timer */ | 2414 | 0, /* non standard timer */ |
2415 | 0, /* open_requests have no inode */ | 2415 | 0, /* open_requests have no inode */ |
2416 | atomic_read(&sk->sk_refcnt), | 2416 | atomic_read(&sk->sk_refcnt), |
@@ -2461,7 +2461,7 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i, int *len) | |||
2461 | timer_active, | 2461 | timer_active, |
2462 | jiffies_delta_to_clock_t(timer_expires - jiffies), | 2462 | jiffies_delta_to_clock_t(timer_expires - jiffies), |
2463 | icsk->icsk_retransmits, | 2463 | icsk->icsk_retransmits, |
2464 | sock_i_uid(sk), | 2464 | from_kuid_munged(seq_user_ns(f), sock_i_uid(sk)), |
2465 | icsk->icsk_probes_out, | 2465 | icsk->icsk_probes_out, |
2466 | sock_i_ino(sk), | 2466 | sock_i_ino(sk), |
2467 | atomic_read(&sk->sk_refcnt), sk, | 2467 | atomic_read(&sk->sk_refcnt), sk, |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 6f6d1aca3c3d..c4e64328d8ba 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -2110,7 +2110,9 @@ static void udp4_format_sock(struct sock *sp, struct seq_file *f, | |||
2110 | bucket, src, srcp, dest, destp, sp->sk_state, | 2110 | bucket, src, srcp, dest, destp, sp->sk_state, |
2111 | sk_wmem_alloc_get(sp), | 2111 | sk_wmem_alloc_get(sp), |
2112 | sk_rmem_alloc_get(sp), | 2112 | sk_rmem_alloc_get(sp), |
2113 | 0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp), | 2113 | 0, 0L, 0, |
2114 | from_kuid_munged(seq_user_ns(f), sock_i_uid(sp)), | ||
2115 | 0, sock_i_ino(sp), | ||
2114 | atomic_read(&sp->sk_refcnt), sp, | 2116 | atomic_read(&sp->sk_refcnt), sp, |
2115 | atomic_read(&sp->sk_drops), len); | 2117 | atomic_read(&sp->sk_drops), len); |
2116 | } | 2118 | } |
diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c index 16d0960062be..d2f336ea82ca 100644 --- a/net/ipv4/udp_diag.c +++ b/net/ipv4/udp_diag.c | |||
@@ -24,7 +24,9 @@ static int sk_diag_dump(struct sock *sk, struct sk_buff *skb, | |||
24 | if (!inet_diag_bc_sk(bc, sk)) | 24 | if (!inet_diag_bc_sk(bc, sk)) |
25 | return 0; | 25 | return 0; |
26 | 26 | ||
27 | return inet_sk_diag_fill(sk, NULL, skb, req, NETLINK_CB(cb->skb).pid, | 27 | return inet_sk_diag_fill(sk, NULL, skb, req, |
28 | sk_user_ns(NETLINK_CB(cb->skb).ssk), | ||
29 | NETLINK_CB(cb->skb).pid, | ||
28 | cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); | 30 | cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); |
29 | } | 31 | } |
30 | 32 | ||
@@ -69,6 +71,7 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb, | |||
69 | goto out; | 71 | goto out; |
70 | 72 | ||
71 | err = inet_sk_diag_fill(sk, NULL, rep, req, | 73 | err = inet_sk_diag_fill(sk, NULL, rep, req, |
74 | sk_user_ns(NETLINK_CB(in_skb).ssk), | ||
72 | NETLINK_CB(in_skb).pid, | 75 | NETLINK_CB(in_skb).pid, |
73 | nlh->nlmsg_seq, 0, nlh); | 76 | nlh->nlmsg_seq, 0, nlh); |
74 | if (err < 0) { | 77 | if (err < 0) { |
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index 9772fbd8a3f5..90bbefb57943 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/seq_file.h> | 22 | #include <linux/seq_file.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/export.h> | 24 | #include <linux/export.h> |
25 | #include <linux/pid_namespace.h> | ||
25 | 26 | ||
26 | #include <net/net_namespace.h> | 27 | #include <net/net_namespace.h> |
27 | #include <net/sock.h> | 28 | #include <net/sock.h> |
@@ -91,6 +92,8 @@ static struct ip6_flowlabel *fl_lookup(struct net *net, __be32 label) | |||
91 | static void fl_free(struct ip6_flowlabel *fl) | 92 | static void fl_free(struct ip6_flowlabel *fl) |
92 | { | 93 | { |
93 | if (fl) { | 94 | if (fl) { |
95 | if (fl->share == IPV6_FL_S_PROCESS) | ||
96 | put_pid(fl->owner.pid); | ||
94 | release_net(fl->fl_net); | 97 | release_net(fl->fl_net); |
95 | kfree(fl->opt); | 98 | kfree(fl->opt); |
96 | } | 99 | } |
@@ -394,10 +397,10 @@ fl_create(struct net *net, struct sock *sk, struct in6_flowlabel_req *freq, | |||
394 | case IPV6_FL_S_ANY: | 397 | case IPV6_FL_S_ANY: |
395 | break; | 398 | break; |
396 | case IPV6_FL_S_PROCESS: | 399 | case IPV6_FL_S_PROCESS: |
397 | fl->owner = current->pid; | 400 | fl->owner.pid = get_task_pid(current, PIDTYPE_PID); |
398 | break; | 401 | break; |
399 | case IPV6_FL_S_USER: | 402 | case IPV6_FL_S_USER: |
400 | fl->owner = current_euid(); | 403 | fl->owner.uid = current_euid(); |
401 | break; | 404 | break; |
402 | default: | 405 | default: |
403 | err = -EINVAL; | 406 | err = -EINVAL; |
@@ -561,7 +564,10 @@ recheck: | |||
561 | err = -EPERM; | 564 | err = -EPERM; |
562 | if (fl1->share == IPV6_FL_S_EXCL || | 565 | if (fl1->share == IPV6_FL_S_EXCL || |
563 | fl1->share != fl->share || | 566 | fl1->share != fl->share || |
564 | fl1->owner != fl->owner) | 567 | ((fl1->share == IPV6_FL_S_PROCESS) && |
568 | (fl1->owner.pid == fl->owner.pid)) || | ||
569 | ((fl1->share == IPV6_FL_S_USER) && | ||
570 | uid_eq(fl1->owner.uid, fl->owner.uid))) | ||
565 | goto release; | 571 | goto release; |
566 | 572 | ||
567 | err = -EINVAL; | 573 | err = -EINVAL; |
@@ -621,6 +627,7 @@ done: | |||
621 | 627 | ||
622 | struct ip6fl_iter_state { | 628 | struct ip6fl_iter_state { |
623 | struct seq_net_private p; | 629 | struct seq_net_private p; |
630 | struct pid_namespace *pid_ns; | ||
624 | int bucket; | 631 | int bucket; |
625 | }; | 632 | }; |
626 | 633 | ||
@@ -699,6 +706,7 @@ static void ip6fl_seq_stop(struct seq_file *seq, void *v) | |||
699 | 706 | ||
700 | static int ip6fl_seq_show(struct seq_file *seq, void *v) | 707 | static int ip6fl_seq_show(struct seq_file *seq, void *v) |
701 | { | 708 | { |
709 | struct ip6fl_iter_state *state = ip6fl_seq_private(seq); | ||
702 | if (v == SEQ_START_TOKEN) | 710 | if (v == SEQ_START_TOKEN) |
703 | seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-32s %s\n", | 711 | seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-32s %s\n", |
704 | "Label", "S", "Owner", "Users", "Linger", "Expires", "Dst", "Opt"); | 712 | "Label", "S", "Owner", "Users", "Linger", "Expires", "Dst", "Opt"); |
@@ -708,7 +716,11 @@ static int ip6fl_seq_show(struct seq_file *seq, void *v) | |||
708 | "%05X %-1d %-6d %-6d %-6ld %-8ld %pi6 %-4d\n", | 716 | "%05X %-1d %-6d %-6d %-6ld %-8ld %pi6 %-4d\n", |
709 | (unsigned int)ntohl(fl->label), | 717 | (unsigned int)ntohl(fl->label), |
710 | fl->share, | 718 | fl->share, |
711 | (int)fl->owner, | 719 | ((fl->share == IPV6_FL_S_PROCESS) ? |
720 | pid_nr_ns(fl->owner.pid, state->pid_ns) : | ||
721 | ((fl->share == IPV6_FL_S_USER) ? | ||
722 | from_kuid_munged(seq_user_ns(seq), fl->owner.uid) : | ||
723 | 0)), | ||
712 | atomic_read(&fl->users), | 724 | atomic_read(&fl->users), |
713 | fl->linger/HZ, | 725 | fl->linger/HZ, |
714 | (long)(fl->expires - jiffies)/HZ, | 726 | (long)(fl->expires - jiffies)/HZ, |
@@ -727,8 +739,29 @@ static const struct seq_operations ip6fl_seq_ops = { | |||
727 | 739 | ||
728 | static int ip6fl_seq_open(struct inode *inode, struct file *file) | 740 | static int ip6fl_seq_open(struct inode *inode, struct file *file) |
729 | { | 741 | { |
730 | return seq_open_net(inode, file, &ip6fl_seq_ops, | 742 | struct seq_file *seq; |
731 | sizeof(struct ip6fl_iter_state)); | 743 | struct ip6fl_iter_state *state; |
744 | int err; | ||
745 | |||
746 | err = seq_open_net(inode, file, &ip6fl_seq_ops, | ||
747 | sizeof(struct ip6fl_iter_state)); | ||
748 | |||
749 | if (!err) { | ||
750 | seq = file->private_data; | ||
751 | state = ip6fl_seq_private(seq); | ||
752 | rcu_read_lock(); | ||
753 | state->pid_ns = get_pid_ns(task_active_pid_ns(current)); | ||
754 | rcu_read_unlock(); | ||
755 | } | ||
756 | return err; | ||
757 | } | ||
758 | |||
759 | static int ip6fl_seq_release(struct inode *inode, struct file *file) | ||
760 | { | ||
761 | struct seq_file *seq = file->private_data; | ||
762 | struct ip6fl_iter_state *state = ip6fl_seq_private(seq); | ||
763 | put_pid_ns(state->pid_ns); | ||
764 | return seq_release_net(inode, file); | ||
732 | } | 765 | } |
733 | 766 | ||
734 | static const struct file_operations ip6fl_seq_fops = { | 767 | static const struct file_operations ip6fl_seq_fops = { |
@@ -736,7 +769,7 @@ static const struct file_operations ip6fl_seq_fops = { | |||
736 | .open = ip6fl_seq_open, | 769 | .open = ip6fl_seq_open, |
737 | .read = seq_read, | 770 | .read = seq_read, |
738 | .llseek = seq_lseek, | 771 | .llseek = seq_lseek, |
739 | .release = seq_release_net, | 772 | .release = ip6fl_seq_release, |
740 | }; | 773 | }; |
741 | 774 | ||
742 | static int __net_init ip6_flowlabel_proc_init(struct net *net) | 775 | static int __net_init ip6_flowlabel_proc_init(struct net *net) |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index ef0579d5bca6..7af88ef01657 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -1251,7 +1251,8 @@ static void raw6_sock_seq_show(struct seq_file *seq, struct sock *sp, int i) | |||
1251 | sk_wmem_alloc_get(sp), | 1251 | sk_wmem_alloc_get(sp), |
1252 | sk_rmem_alloc_get(sp), | 1252 | sk_rmem_alloc_get(sp), |
1253 | 0, 0L, 0, | 1253 | 0, 0L, 0, |
1254 | sock_i_uid(sp), 0, | 1254 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)), |
1255 | 0, | ||
1255 | sock_i_ino(sp), | 1256 | sock_i_ino(sp), |
1256 | atomic_read(&sp->sk_refcnt), sp, atomic_read(&sp->sk_drops)); | 1257 | atomic_read(&sp->sk_refcnt), sp, atomic_read(&sp->sk_drops)); |
1257 | } | 1258 | } |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index cd49de3678fb..f99b81d53cca 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -1828,7 +1828,7 @@ static void tcp_v6_destroy_sock(struct sock *sk) | |||
1828 | #ifdef CONFIG_PROC_FS | 1828 | #ifdef CONFIG_PROC_FS |
1829 | /* Proc filesystem TCPv6 sock list dumping. */ | 1829 | /* Proc filesystem TCPv6 sock list dumping. */ |
1830 | static void get_openreq6(struct seq_file *seq, | 1830 | static void get_openreq6(struct seq_file *seq, |
1831 | const struct sock *sk, struct request_sock *req, int i, int uid) | 1831 | const struct sock *sk, struct request_sock *req, int i, kuid_t uid) |
1832 | { | 1832 | { |
1833 | int ttd = req->expires - jiffies; | 1833 | int ttd = req->expires - jiffies; |
1834 | const struct in6_addr *src = &inet6_rsk(req)->loc_addr; | 1834 | const struct in6_addr *src = &inet6_rsk(req)->loc_addr; |
@@ -1852,7 +1852,7 @@ static void get_openreq6(struct seq_file *seq, | |||
1852 | 1, /* timers active (only the expire timer) */ | 1852 | 1, /* timers active (only the expire timer) */ |
1853 | jiffies_to_clock_t(ttd), | 1853 | jiffies_to_clock_t(ttd), |
1854 | req->retrans, | 1854 | req->retrans, |
1855 | uid, | 1855 | from_kuid_munged(seq_user_ns(seq), uid), |
1856 | 0, /* non standard timer */ | 1856 | 0, /* non standard timer */ |
1857 | 0, /* open_requests have no inode */ | 1857 | 0, /* open_requests have no inode */ |
1858 | 0, req); | 1858 | 0, req); |
@@ -1902,7 +1902,7 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) | |||
1902 | timer_active, | 1902 | timer_active, |
1903 | jiffies_delta_to_clock_t(timer_expires - jiffies), | 1903 | jiffies_delta_to_clock_t(timer_expires - jiffies), |
1904 | icsk->icsk_retransmits, | 1904 | icsk->icsk_retransmits, |
1905 | sock_i_uid(sp), | 1905 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)), |
1906 | icsk->icsk_probes_out, | 1906 | icsk->icsk_probes_out, |
1907 | sock_i_ino(sp), | 1907 | sock_i_ino(sp), |
1908 | atomic_read(&sp->sk_refcnt), sp, | 1908 | atomic_read(&sp->sk_refcnt), sp, |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 99d0077b56b8..bbdff07eebe1 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -1458,7 +1458,8 @@ static void udp6_sock_seq_show(struct seq_file *seq, struct sock *sp, int bucket | |||
1458 | sk_wmem_alloc_get(sp), | 1458 | sk_wmem_alloc_get(sp), |
1459 | sk_rmem_alloc_get(sp), | 1459 | sk_rmem_alloc_get(sp), |
1460 | 0, 0L, 0, | 1460 | 0, 0L, 0, |
1461 | sock_i_uid(sp), 0, | 1461 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)), |
1462 | 0, | ||
1462 | sock_i_ino(sp), | 1463 | sock_i_ino(sp), |
1463 | atomic_read(&sp->sk_refcnt), sp, | 1464 | atomic_read(&sp->sk_refcnt), sp, |
1464 | atomic_read(&sp->sk_drops)); | 1465 | atomic_read(&sp->sk_drops)); |
diff --git a/net/ipx/ipx_proc.c b/net/ipx/ipx_proc.c index f8ba30dfecae..02ff7f2f60d4 100644 --- a/net/ipx/ipx_proc.c +++ b/net/ipx/ipx_proc.c | |||
@@ -217,7 +217,8 @@ static int ipx_seq_socket_show(struct seq_file *seq, void *v) | |||
217 | seq_printf(seq, "%08X %08X %02X %03d\n", | 217 | seq_printf(seq, "%08X %08X %02X %03d\n", |
218 | sk_wmem_alloc_get(s), | 218 | sk_wmem_alloc_get(s), |
219 | sk_rmem_alloc_get(s), | 219 | sk_rmem_alloc_get(s), |
220 | s->sk_state, SOCK_INODE(s->sk_socket)->i_uid); | 220 | s->sk_state, |
221 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(s))); | ||
221 | out: | 222 | out: |
222 | return 0; | 223 | return 0; |
223 | } | 224 | } |
diff --git a/net/key/af_key.c b/net/key/af_key.c index ec7d161c129b..334f93b8cfcb 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
@@ -3661,7 +3661,7 @@ static int pfkey_seq_show(struct seq_file *f, void *v) | |||
3661 | atomic_read(&s->sk_refcnt), | 3661 | atomic_read(&s->sk_refcnt), |
3662 | sk_rmem_alloc_get(s), | 3662 | sk_rmem_alloc_get(s), |
3663 | sk_wmem_alloc_get(s), | 3663 | sk_wmem_alloc_get(s), |
3664 | sock_i_uid(s), | 3664 | from_kuid_munged(seq_user_ns(f), sock_i_uid(s)), |
3665 | sock_i_ino(s) | 3665 | sock_i_ino(s) |
3666 | ); | 3666 | ); |
3667 | return 0; | 3667 | return 0; |
diff --git a/net/llc/llc_proc.c b/net/llc/llc_proc.c index a1839c004357..7b4799cfbf8d 100644 --- a/net/llc/llc_proc.c +++ b/net/llc/llc_proc.c | |||
@@ -151,7 +151,7 @@ static int llc_seq_socket_show(struct seq_file *seq, void *v) | |||
151 | sk_wmem_alloc_get(sk), | 151 | sk_wmem_alloc_get(sk), |
152 | sk_rmem_alloc_get(sk) - llc->copied_seq, | 152 | sk_rmem_alloc_get(sk) - llc->copied_seq, |
153 | sk->sk_state, | 153 | sk->sk_state, |
154 | sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_uid : -1, | 154 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)), |
155 | llc->link); | 155 | llc->link); |
156 | out: | 156 | out: |
157 | return 0; | 157 | return 0; |
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 169ab59ed9d4..4142aac17c3c 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c | |||
@@ -55,6 +55,7 @@ struct nfulnl_instance { | |||
55 | unsigned int qlen; /* number of nlmsgs in skb */ | 55 | unsigned int qlen; /* number of nlmsgs in skb */ |
56 | struct sk_buff *skb; /* pre-allocatd skb */ | 56 | struct sk_buff *skb; /* pre-allocatd skb */ |
57 | struct timer_list timer; | 57 | struct timer_list timer; |
58 | struct user_namespace *peer_user_ns; /* User namespace of the peer process */ | ||
58 | int peer_pid; /* PID of the peer process */ | 59 | int peer_pid; /* PID of the peer process */ |
59 | 60 | ||
60 | /* configurable parameters */ | 61 | /* configurable parameters */ |
@@ -132,7 +133,7 @@ instance_put(struct nfulnl_instance *inst) | |||
132 | static void nfulnl_timer(unsigned long data); | 133 | static void nfulnl_timer(unsigned long data); |
133 | 134 | ||
134 | static struct nfulnl_instance * | 135 | static struct nfulnl_instance * |
135 | instance_create(u_int16_t group_num, int pid) | 136 | instance_create(u_int16_t group_num, int pid, struct user_namespace *user_ns) |
136 | { | 137 | { |
137 | struct nfulnl_instance *inst; | 138 | struct nfulnl_instance *inst; |
138 | int err; | 139 | int err; |
@@ -162,6 +163,7 @@ instance_create(u_int16_t group_num, int pid) | |||
162 | 163 | ||
163 | setup_timer(&inst->timer, nfulnl_timer, (unsigned long)inst); | 164 | setup_timer(&inst->timer, nfulnl_timer, (unsigned long)inst); |
164 | 165 | ||
166 | inst->peer_user_ns = user_ns; | ||
165 | inst->peer_pid = pid; | 167 | inst->peer_pid = pid; |
166 | inst->group_num = group_num; | 168 | inst->group_num = group_num; |
167 | 169 | ||
@@ -503,8 +505,11 @@ __build_packet_message(struct nfulnl_instance *inst, | |||
503 | read_lock_bh(&skb->sk->sk_callback_lock); | 505 | read_lock_bh(&skb->sk->sk_callback_lock); |
504 | if (skb->sk->sk_socket && skb->sk->sk_socket->file) { | 506 | if (skb->sk->sk_socket && skb->sk->sk_socket->file) { |
505 | struct file *file = skb->sk->sk_socket->file; | 507 | struct file *file = skb->sk->sk_socket->file; |
506 | __be32 uid = htonl(file->f_cred->fsuid); | 508 | __be32 uid = htonl(from_kuid_munged(inst->peer_user_ns, |
507 | __be32 gid = htonl(file->f_cred->fsgid); | 509 | file->f_cred->fsuid)); |
510 | __be32 gid = htonl(from_kgid_munged(inst->peer_user_ns, | ||
511 | file->f_cred->fsgid)); | ||
512 | /* need to unlock here since NLA_PUT may goto */ | ||
508 | read_unlock_bh(&skb->sk->sk_callback_lock); | 513 | read_unlock_bh(&skb->sk->sk_callback_lock); |
509 | if (nla_put_be32(inst->skb, NFULA_UID, uid) || | 514 | if (nla_put_be32(inst->skb, NFULA_UID, uid) || |
510 | nla_put_be32(inst->skb, NFULA_GID, gid)) | 515 | nla_put_be32(inst->skb, NFULA_GID, gid)) |
@@ -783,7 +788,8 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, | |||
783 | } | 788 | } |
784 | 789 | ||
785 | inst = instance_create(group_num, | 790 | inst = instance_create(group_num, |
786 | NETLINK_CB(skb).pid); | 791 | NETLINK_CB(skb).pid, |
792 | sk_user_ns(NETLINK_CB(skb).ssk)); | ||
787 | if (IS_ERR(inst)) { | 793 | if (IS_ERR(inst)) { |
788 | ret = PTR_ERR(inst); | 794 | ret = PTR_ERR(inst); |
789 | goto out; | 795 | goto out; |
diff --git a/net/netfilter/xt_LOG.c b/net/netfilter/xt_LOG.c index ff5f75fddb15..02a2bf49dcbd 100644 --- a/net/netfilter/xt_LOG.c +++ b/net/netfilter/xt_LOG.c | |||
@@ -363,10 +363,12 @@ static void dump_ipv4_packet(struct sbuff *m, | |||
363 | /* Max length: 15 "UID=4294967295 " */ | 363 | /* Max length: 15 "UID=4294967295 " */ |
364 | if ((logflags & XT_LOG_UID) && !iphoff && skb->sk) { | 364 | if ((logflags & XT_LOG_UID) && !iphoff && skb->sk) { |
365 | read_lock_bh(&skb->sk->sk_callback_lock); | 365 | read_lock_bh(&skb->sk->sk_callback_lock); |
366 | if (skb->sk->sk_socket && skb->sk->sk_socket->file) | 366 | if (skb->sk->sk_socket && skb->sk->sk_socket->file) { |
367 | const struct cred *cred = skb->sk->sk_socket->file->f_cred; | ||
367 | sb_add(m, "UID=%u GID=%u ", | 368 | sb_add(m, "UID=%u GID=%u ", |
368 | skb->sk->sk_socket->file->f_cred->fsuid, | 369 | from_kuid_munged(&init_user_ns, cred->fsuid), |
369 | skb->sk->sk_socket->file->f_cred->fsgid); | 370 | from_kgid_munged(&init_user_ns, cred->fsgid)); |
371 | } | ||
370 | read_unlock_bh(&skb->sk->sk_callback_lock); | 372 | read_unlock_bh(&skb->sk->sk_callback_lock); |
371 | } | 373 | } |
372 | 374 | ||
@@ -719,10 +721,12 @@ static void dump_ipv6_packet(struct sbuff *m, | |||
719 | /* Max length: 15 "UID=4294967295 " */ | 721 | /* Max length: 15 "UID=4294967295 " */ |
720 | if ((logflags & XT_LOG_UID) && recurse && skb->sk) { | 722 | if ((logflags & XT_LOG_UID) && recurse && skb->sk) { |
721 | read_lock_bh(&skb->sk->sk_callback_lock); | 723 | read_lock_bh(&skb->sk->sk_callback_lock); |
722 | if (skb->sk->sk_socket && skb->sk->sk_socket->file) | 724 | if (skb->sk->sk_socket && skb->sk->sk_socket->file) { |
725 | const struct cred *cred = skb->sk->sk_socket->file->f_cred; | ||
723 | sb_add(m, "UID=%u GID=%u ", | 726 | sb_add(m, "UID=%u GID=%u ", |
724 | skb->sk->sk_socket->file->f_cred->fsuid, | 727 | from_kuid_munged(&init_user_ns, cred->fsuid), |
725 | skb->sk->sk_socket->file->f_cred->fsgid); | 728 | from_kgid_munged(&init_user_ns, cred->fsgid)); |
729 | } | ||
726 | read_unlock_bh(&skb->sk->sk_callback_lock); | 730 | read_unlock_bh(&skb->sk->sk_callback_lock); |
727 | } | 731 | } |
728 | 732 | ||
diff --git a/net/netfilter/xt_owner.c b/net/netfilter/xt_owner.c index 772d7389b337..ca2e577ed8ac 100644 --- a/net/netfilter/xt_owner.c +++ b/net/netfilter/xt_owner.c | |||
@@ -17,6 +17,17 @@ | |||
17 | #include <linux/netfilter/x_tables.h> | 17 | #include <linux/netfilter/x_tables.h> |
18 | #include <linux/netfilter/xt_owner.h> | 18 | #include <linux/netfilter/xt_owner.h> |
19 | 19 | ||
20 | static int owner_check(const struct xt_mtchk_param *par) | ||
21 | { | ||
22 | struct xt_owner_match_info *info = par->matchinfo; | ||
23 | |||
24 | /* For now only allow adding matches from the initial user namespace */ | ||
25 | if ((info->match & (XT_OWNER_UID|XT_OWNER_GID)) && | ||
26 | (current_user_ns() != &init_user_ns)) | ||
27 | return -EINVAL; | ||
28 | return 0; | ||
29 | } | ||
30 | |||
20 | static bool | 31 | static bool |
21 | owner_mt(const struct sk_buff *skb, struct xt_action_param *par) | 32 | owner_mt(const struct sk_buff *skb, struct xt_action_param *par) |
22 | { | 33 | { |
@@ -37,17 +48,23 @@ owner_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
37 | return ((info->match ^ info->invert) & | 48 | return ((info->match ^ info->invert) & |
38 | (XT_OWNER_UID | XT_OWNER_GID)) == 0; | 49 | (XT_OWNER_UID | XT_OWNER_GID)) == 0; |
39 | 50 | ||
40 | if (info->match & XT_OWNER_UID) | 51 | if (info->match & XT_OWNER_UID) { |
41 | if ((filp->f_cred->fsuid >= info->uid_min && | 52 | kuid_t uid_min = make_kuid(&init_user_ns, info->uid_min); |
42 | filp->f_cred->fsuid <= info->uid_max) ^ | 53 | kuid_t uid_max = make_kuid(&init_user_ns, info->uid_max); |
54 | if ((uid_gte(filp->f_cred->fsuid, uid_min) && | ||
55 | uid_lte(filp->f_cred->fsuid, uid_max)) ^ | ||
43 | !(info->invert & XT_OWNER_UID)) | 56 | !(info->invert & XT_OWNER_UID)) |
44 | return false; | 57 | return false; |
58 | } | ||
45 | 59 | ||
46 | if (info->match & XT_OWNER_GID) | 60 | if (info->match & XT_OWNER_GID) { |
47 | if ((filp->f_cred->fsgid >= info->gid_min && | 61 | kgid_t gid_min = make_kgid(&init_user_ns, info->gid_min); |
48 | filp->f_cred->fsgid <= info->gid_max) ^ | 62 | kgid_t gid_max = make_kgid(&init_user_ns, info->gid_max); |
63 | if ((gid_gte(filp->f_cred->fsgid, gid_min) && | ||
64 | gid_lte(filp->f_cred->fsgid, gid_max)) ^ | ||
49 | !(info->invert & XT_OWNER_GID)) | 65 | !(info->invert & XT_OWNER_GID)) |
50 | return false; | 66 | return false; |
67 | } | ||
51 | 68 | ||
52 | return true; | 69 | return true; |
53 | } | 70 | } |
@@ -56,6 +73,7 @@ static struct xt_match owner_mt_reg __read_mostly = { | |||
56 | .name = "owner", | 73 | .name = "owner", |
57 | .revision = 1, | 74 | .revision = 1, |
58 | .family = NFPROTO_UNSPEC, | 75 | .family = NFPROTO_UNSPEC, |
76 | .checkentry = owner_check, | ||
59 | .match = owner_mt, | 77 | .match = owner_mt, |
60 | .matchsize = sizeof(struct xt_owner_match_info), | 78 | .matchsize = sizeof(struct xt_owner_match_info), |
61 | .hooks = (1 << NF_INET_LOCAL_OUT) | | 79 | .hooks = (1 << NF_INET_LOCAL_OUT) | |
diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c index ae2ad1eec8d0..4635c9b00459 100644 --- a/net/netfilter/xt_recent.c +++ b/net/netfilter/xt_recent.c | |||
@@ -317,6 +317,8 @@ static int recent_mt_check(const struct xt_mtchk_param *par, | |||
317 | struct recent_table *t; | 317 | struct recent_table *t; |
318 | #ifdef CONFIG_PROC_FS | 318 | #ifdef CONFIG_PROC_FS |
319 | struct proc_dir_entry *pde; | 319 | struct proc_dir_entry *pde; |
320 | kuid_t uid; | ||
321 | kgid_t gid; | ||
320 | #endif | 322 | #endif |
321 | unsigned int i; | 323 | unsigned int i; |
322 | int ret = -EINVAL; | 324 | int ret = -EINVAL; |
@@ -372,6 +374,13 @@ static int recent_mt_check(const struct xt_mtchk_param *par, | |||
372 | for (i = 0; i < ip_list_hash_size; i++) | 374 | for (i = 0; i < ip_list_hash_size; i++) |
373 | INIT_LIST_HEAD(&t->iphash[i]); | 375 | INIT_LIST_HEAD(&t->iphash[i]); |
374 | #ifdef CONFIG_PROC_FS | 376 | #ifdef CONFIG_PROC_FS |
377 | uid = make_kuid(&init_user_ns, ip_list_uid); | ||
378 | gid = make_kgid(&init_user_ns, ip_list_gid); | ||
379 | if (!uid_valid(uid) || !gid_valid(gid)) { | ||
380 | kfree(t); | ||
381 | ret = -EINVAL; | ||
382 | goto out; | ||
383 | } | ||
375 | pde = proc_create_data(t->name, ip_list_perms, recent_net->xt_recent, | 384 | pde = proc_create_data(t->name, ip_list_perms, recent_net->xt_recent, |
376 | &recent_mt_fops, t); | 385 | &recent_mt_fops, t); |
377 | if (pde == NULL) { | 386 | if (pde == NULL) { |
@@ -379,8 +388,8 @@ static int recent_mt_check(const struct xt_mtchk_param *par, | |||
379 | ret = -ENOMEM; | 388 | ret = -ENOMEM; |
380 | goto out; | 389 | goto out; |
381 | } | 390 | } |
382 | pde->uid = ip_list_uid; | 391 | pde->uid = uid; |
383 | pde->gid = ip_list_gid; | 392 | pde->gid = gid; |
384 | #endif | 393 | #endif |
385 | spin_lock_bh(&recent_lock); | 394 | spin_lock_bh(&recent_lock); |
386 | list_add_tail(&t->list, &recent_net->tables); | 395 | list_add_tail(&t->list, &recent_net->tables); |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 1445d73533ed..aacfb1df9567 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -912,7 +912,8 @@ static void netlink_rcv_wake(struct sock *sk) | |||
912 | wake_up_interruptible(&nlk->wait); | 912 | wake_up_interruptible(&nlk->wait); |
913 | } | 913 | } |
914 | 914 | ||
915 | static int netlink_unicast_kernel(struct sock *sk, struct sk_buff *skb) | 915 | static int netlink_unicast_kernel(struct sock *sk, struct sk_buff *skb, |
916 | struct sock *ssk) | ||
916 | { | 917 | { |
917 | int ret; | 918 | int ret; |
918 | struct netlink_sock *nlk = nlk_sk(sk); | 919 | struct netlink_sock *nlk = nlk_sk(sk); |
@@ -921,6 +922,7 @@ static int netlink_unicast_kernel(struct sock *sk, struct sk_buff *skb) | |||
921 | if (nlk->netlink_rcv != NULL) { | 922 | if (nlk->netlink_rcv != NULL) { |
922 | ret = skb->len; | 923 | ret = skb->len; |
923 | skb_set_owner_r(skb, sk); | 924 | skb_set_owner_r(skb, sk); |
925 | NETLINK_CB(skb).ssk = ssk; | ||
924 | nlk->netlink_rcv(skb); | 926 | nlk->netlink_rcv(skb); |
925 | consume_skb(skb); | 927 | consume_skb(skb); |
926 | } else { | 928 | } else { |
@@ -947,7 +949,7 @@ retry: | |||
947 | return PTR_ERR(sk); | 949 | return PTR_ERR(sk); |
948 | } | 950 | } |
949 | if (netlink_is_kernel(sk)) | 951 | if (netlink_is_kernel(sk)) |
950 | return netlink_unicast_kernel(sk, skb); | 952 | return netlink_unicast_kernel(sk, skb, ssk); |
951 | 953 | ||
952 | if (sk_filter(sk, skb)) { | 954 | if (sk_filter(sk, skb)) { |
953 | err = skb->len; | 955 | err = skb->len; |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index f220c5bdb71f..5dafe84d75d5 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -3749,7 +3749,7 @@ static int packet_seq_show(struct seq_file *seq, void *v) | |||
3749 | po->ifindex, | 3749 | po->ifindex, |
3750 | po->running, | 3750 | po->running, |
3751 | atomic_read(&s->sk_rmem_alloc), | 3751 | atomic_read(&s->sk_rmem_alloc), |
3752 | sock_i_uid(s), | 3752 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(s)), |
3753 | sock_i_ino(s)); | 3753 | sock_i_ino(s)); |
3754 | } | 3754 | } |
3755 | 3755 | ||
diff --git a/net/phonet/socket.c b/net/phonet/socket.c index 0acc943f713a..b7e982782255 100644 --- a/net/phonet/socket.c +++ b/net/phonet/socket.c | |||
@@ -612,7 +612,8 @@ static int pn_sock_seq_show(struct seq_file *seq, void *v) | |||
612 | sk->sk_protocol, pn->sobject, pn->dobject, | 612 | sk->sk_protocol, pn->sobject, pn->dobject, |
613 | pn->resource, sk->sk_state, | 613 | pn->resource, sk->sk_state, |
614 | sk_wmem_alloc_get(sk), sk_rmem_alloc_get(sk), | 614 | sk_wmem_alloc_get(sk), sk_rmem_alloc_get(sk), |
615 | sock_i_uid(sk), sock_i_ino(sk), | 615 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)), |
616 | sock_i_ino(sk), | ||
616 | atomic_read(&sk->sk_refcnt), sk, | 617 | atomic_read(&sk->sk_refcnt), sk, |
617 | atomic_read(&sk->sk_drops), &len); | 618 | atomic_read(&sk->sk_drops), &len); |
618 | } | 619 | } |
@@ -796,7 +797,8 @@ static int pn_res_seq_show(struct seq_file *seq, void *v) | |||
796 | struct sock *sk = *psk; | 797 | struct sock *sk = *psk; |
797 | 798 | ||
798 | seq_printf(seq, "%02X %5d %lu%n", | 799 | seq_printf(seq, "%02X %5d %lu%n", |
799 | (int) (psk - pnres.sk), sock_i_uid(sk), | 800 | (int) (psk - pnres.sk), |
801 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)), | ||
800 | sock_i_ino(sk), &len); | 802 | sock_i_ino(sk), &len); |
801 | } | 803 | } |
802 | seq_printf(seq, "%*s\n", 63 - len, ""); | 804 | seq_printf(seq, "%*s\n", 63 - len, ""); |
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 6dd1131f2ec1..dc3ef5aef355 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c | |||
@@ -319,7 +319,7 @@ replay: | |||
319 | } | 319 | } |
320 | } | 320 | } |
321 | 321 | ||
322 | err = tp->ops->change(tp, cl, t->tcm_handle, tca, &fh); | 322 | err = tp->ops->change(skb, tp, cl, t->tcm_handle, tca, &fh); |
323 | if (err == 0) { | 323 | if (err == 0) { |
324 | if (tp_created) { | 324 | if (tp_created) { |
325 | spin_lock_bh(root_lock); | 325 | spin_lock_bh(root_lock); |
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c index 590960a22a77..344a11b342e5 100644 --- a/net/sched/cls_basic.c +++ b/net/sched/cls_basic.c | |||
@@ -162,7 +162,8 @@ errout: | |||
162 | return err; | 162 | return err; |
163 | } | 163 | } |
164 | 164 | ||
165 | static int basic_change(struct tcf_proto *tp, unsigned long base, u32 handle, | 165 | static int basic_change(struct sk_buff *in_skb, |
166 | struct tcf_proto *tp, unsigned long base, u32 handle, | ||
166 | struct nlattr **tca, unsigned long *arg) | 167 | struct nlattr **tca, unsigned long *arg) |
167 | { | 168 | { |
168 | int err; | 169 | int err; |
diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c index 7743ea8d1d38..91de66695b4a 100644 --- a/net/sched/cls_cgroup.c +++ b/net/sched/cls_cgroup.c | |||
@@ -151,7 +151,8 @@ static const struct nla_policy cgroup_policy[TCA_CGROUP_MAX + 1] = { | |||
151 | [TCA_CGROUP_EMATCHES] = { .type = NLA_NESTED }, | 151 | [TCA_CGROUP_EMATCHES] = { .type = NLA_NESTED }, |
152 | }; | 152 | }; |
153 | 153 | ||
154 | static int cls_cgroup_change(struct tcf_proto *tp, unsigned long base, | 154 | static int cls_cgroup_change(struct sk_buff *in_skb, |
155 | struct tcf_proto *tp, unsigned long base, | ||
155 | u32 handle, struct nlattr **tca, | 156 | u32 handle, struct nlattr **tca, |
156 | unsigned long *arg) | 157 | unsigned long *arg) |
157 | { | 158 | { |
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c index ccd08c8dc6a7..ce82d0cb1b47 100644 --- a/net/sched/cls_flow.c +++ b/net/sched/cls_flow.c | |||
@@ -193,15 +193,19 @@ static u32 flow_get_rtclassid(const struct sk_buff *skb) | |||
193 | 193 | ||
194 | static u32 flow_get_skuid(const struct sk_buff *skb) | 194 | static u32 flow_get_skuid(const struct sk_buff *skb) |
195 | { | 195 | { |
196 | if (skb->sk && skb->sk->sk_socket && skb->sk->sk_socket->file) | 196 | if (skb->sk && skb->sk->sk_socket && skb->sk->sk_socket->file) { |
197 | return skb->sk->sk_socket->file->f_cred->fsuid; | 197 | kuid_t skuid = skb->sk->sk_socket->file->f_cred->fsuid; |
198 | return from_kuid(&init_user_ns, skuid); | ||
199 | } | ||
198 | return 0; | 200 | return 0; |
199 | } | 201 | } |
200 | 202 | ||
201 | static u32 flow_get_skgid(const struct sk_buff *skb) | 203 | static u32 flow_get_skgid(const struct sk_buff *skb) |
202 | { | 204 | { |
203 | if (skb->sk && skb->sk->sk_socket && skb->sk->sk_socket->file) | 205 | if (skb->sk && skb->sk->sk_socket && skb->sk->sk_socket->file) { |
204 | return skb->sk->sk_socket->file->f_cred->fsgid; | 206 | kgid_t skgid = skb->sk->sk_socket->file->f_cred->fsgid; |
207 | return from_kgid(&init_user_ns, skgid); | ||
208 | } | ||
205 | return 0; | 209 | return 0; |
206 | } | 210 | } |
207 | 211 | ||
@@ -347,7 +351,8 @@ static const struct nla_policy flow_policy[TCA_FLOW_MAX + 1] = { | |||
347 | [TCA_FLOW_PERTURB] = { .type = NLA_U32 }, | 351 | [TCA_FLOW_PERTURB] = { .type = NLA_U32 }, |
348 | }; | 352 | }; |
349 | 353 | ||
350 | static int flow_change(struct tcf_proto *tp, unsigned long base, | 354 | static int flow_change(struct sk_buff *in_skb, |
355 | struct tcf_proto *tp, unsigned long base, | ||
351 | u32 handle, struct nlattr **tca, | 356 | u32 handle, struct nlattr **tca, |
352 | unsigned long *arg) | 357 | unsigned long *arg) |
353 | { | 358 | { |
@@ -386,6 +391,10 @@ static int flow_change(struct tcf_proto *tp, unsigned long base, | |||
386 | 391 | ||
387 | if (fls(keymask) - 1 > FLOW_KEY_MAX) | 392 | if (fls(keymask) - 1 > FLOW_KEY_MAX) |
388 | return -EOPNOTSUPP; | 393 | return -EOPNOTSUPP; |
394 | |||
395 | if ((keymask & (FLOW_KEY_SKUID|FLOW_KEY_SKGID)) && | ||
396 | sk_user_ns(NETLINK_CB(in_skb).ssk) != &init_user_ns) | ||
397 | return -EOPNOTSUPP; | ||
389 | } | 398 | } |
390 | 399 | ||
391 | err = tcf_exts_validate(tp, tb, tca[TCA_RATE], &e, &flow_ext_map); | 400 | err = tcf_exts_validate(tp, tb, tca[TCA_RATE], &e, &flow_ext_map); |
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c index 8384a4797240..4075a0aef2aa 100644 --- a/net/sched/cls_fw.c +++ b/net/sched/cls_fw.c | |||
@@ -233,7 +233,8 @@ errout: | |||
233 | return err; | 233 | return err; |
234 | } | 234 | } |
235 | 235 | ||
236 | static int fw_change(struct tcf_proto *tp, unsigned long base, | 236 | static int fw_change(struct sk_buff *in_skb, |
237 | struct tcf_proto *tp, unsigned long base, | ||
237 | u32 handle, | 238 | u32 handle, |
238 | struct nlattr **tca, | 239 | struct nlattr **tca, |
239 | unsigned long *arg) | 240 | unsigned long *arg) |
diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c index 44f405cb9aaf..c10d57bf98f2 100644 --- a/net/sched/cls_route.c +++ b/net/sched/cls_route.c | |||
@@ -427,7 +427,8 @@ errout: | |||
427 | return err; | 427 | return err; |
428 | } | 428 | } |
429 | 429 | ||
430 | static int route4_change(struct tcf_proto *tp, unsigned long base, | 430 | static int route4_change(struct sk_buff *in_skb, |
431 | struct tcf_proto *tp, unsigned long base, | ||
431 | u32 handle, | 432 | u32 handle, |
432 | struct nlattr **tca, | 433 | struct nlattr **tca, |
433 | unsigned long *arg) | 434 | unsigned long *arg) |
diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h index 18ab93ec8d7e..494bbb90924a 100644 --- a/net/sched/cls_rsvp.h +++ b/net/sched/cls_rsvp.h | |||
@@ -416,7 +416,8 @@ static const struct nla_policy rsvp_policy[TCA_RSVP_MAX + 1] = { | |||
416 | [TCA_RSVP_PINFO] = { .len = sizeof(struct tc_rsvp_pinfo) }, | 416 | [TCA_RSVP_PINFO] = { .len = sizeof(struct tc_rsvp_pinfo) }, |
417 | }; | 417 | }; |
418 | 418 | ||
419 | static int rsvp_change(struct tcf_proto *tp, unsigned long base, | 419 | static int rsvp_change(struct sk_buff *in_skb, |
420 | struct tcf_proto *tp, unsigned long base, | ||
420 | u32 handle, | 421 | u32 handle, |
421 | struct nlattr **tca, | 422 | struct nlattr **tca, |
422 | unsigned long *arg) | 423 | unsigned long *arg) |
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c index fe29420d0b0e..a1293b4ab7a1 100644 --- a/net/sched/cls_tcindex.c +++ b/net/sched/cls_tcindex.c | |||
@@ -332,7 +332,8 @@ errout: | |||
332 | } | 332 | } |
333 | 333 | ||
334 | static int | 334 | static int |
335 | tcindex_change(struct tcf_proto *tp, unsigned long base, u32 handle, | 335 | tcindex_change(struct sk_buff *in_skb, |
336 | struct tcf_proto *tp, unsigned long base, u32 handle, | ||
336 | struct nlattr **tca, unsigned long *arg) | 337 | struct nlattr **tca, unsigned long *arg) |
337 | { | 338 | { |
338 | struct nlattr *opt = tca[TCA_OPTIONS]; | 339 | struct nlattr *opt = tca[TCA_OPTIONS]; |
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index d45373fb00b9..c7c27bc91b5a 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c | |||
@@ -544,7 +544,8 @@ errout: | |||
544 | return err; | 544 | return err; |
545 | } | 545 | } |
546 | 546 | ||
547 | static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle, | 547 | static int u32_change(struct sk_buff *in_skb, |
548 | struct tcf_proto *tp, unsigned long base, u32 handle, | ||
548 | struct nlattr **tca, | 549 | struct nlattr **tca, |
549 | unsigned long *arg) | 550 | unsigned long *arg) |
550 | { | 551 | { |
diff --git a/net/sctp/proc.c b/net/sctp/proc.c index d9cb2ab149fe..c3bea269faf4 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c | |||
@@ -220,7 +220,8 @@ static int sctp_eps_seq_show(struct seq_file *seq, void *v) | |||
220 | seq_printf(seq, "%8pK %8pK %-3d %-3d %-4d %-5d %5d %5lu ", ep, sk, | 220 | seq_printf(seq, "%8pK %8pK %-3d %-3d %-4d %-5d %5d %5lu ", ep, sk, |
221 | sctp_sk(sk)->type, sk->sk_state, hash, | 221 | sctp_sk(sk)->type, sk->sk_state, hash, |
222 | epb->bind_addr.port, | 222 | epb->bind_addr.port, |
223 | sock_i_uid(sk), sock_i_ino(sk)); | 223 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)), |
224 | sock_i_ino(sk)); | ||
224 | 225 | ||
225 | sctp_seq_dump_local_addrs(seq, epb); | 226 | sctp_seq_dump_local_addrs(seq, epb); |
226 | seq_printf(seq, "\n"); | 227 | seq_printf(seq, "\n"); |
@@ -332,7 +333,8 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v) | |||
332 | assoc->assoc_id, | 333 | assoc->assoc_id, |
333 | assoc->sndbuf_used, | 334 | assoc->sndbuf_used, |
334 | atomic_read(&assoc->rmem_alloc), | 335 | atomic_read(&assoc->rmem_alloc), |
335 | sock_i_uid(sk), sock_i_ino(sk), | 336 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)), |
337 | sock_i_ino(sk), | ||
336 | epb->bind_addr.port, | 338 | epb->bind_addr.port, |
337 | assoc->peer.port); | 339 | assoc->peer.port); |
338 | seq_printf(seq, " "); | 340 | seq_printf(seq, " "); |