Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace
This is an initial merge in of Eric Biederman's work to start adding user namespace support to the networking. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Коммит
e6acb38480
|
@ -120,8 +120,8 @@ struct tun_sock;
|
|||
struct tun_struct {
|
||||
struct tun_file *tfile;
|
||||
unsigned int flags;
|
||||
uid_t owner;
|
||||
gid_t group;
|
||||
kuid_t owner;
|
||||
kgid_t group;
|
||||
|
||||
struct net_device *dev;
|
||||
netdev_features_t set_features;
|
||||
|
@ -1031,8 +1031,8 @@ static void tun_setup(struct net_device *dev)
|
|||
{
|
||||
struct tun_struct *tun = netdev_priv(dev);
|
||||
|
||||
tun->owner = -1;
|
||||
tun->group = -1;
|
||||
tun->owner = INVALID_UID;
|
||||
tun->group = INVALID_GID;
|
||||
|
||||
dev->ethtool_ops = &tun_ethtool_ops;
|
||||
dev->destructor = tun_free_netdev;
|
||||
|
@ -1155,14 +1155,20 @@ static ssize_t tun_show_owner(struct device *dev, struct device_attribute *attr,
|
|||
char *buf)
|
||||
{
|
||||
struct tun_struct *tun = netdev_priv(to_net_dev(dev));
|
||||
return sprintf(buf, "%d\n", tun->owner);
|
||||
return uid_valid(tun->owner)?
|
||||
sprintf(buf, "%u\n",
|
||||
from_kuid_munged(current_user_ns(), tun->owner)):
|
||||
sprintf(buf, "-1\n");
|
||||
}
|
||||
|
||||
static ssize_t tun_show_group(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct tun_struct *tun = netdev_priv(to_net_dev(dev));
|
||||
return sprintf(buf, "%d\n", tun->group);
|
||||
return gid_valid(tun->group) ?
|
||||
sprintf(buf, "%u\n",
|
||||
from_kgid_munged(current_user_ns(), tun->group)):
|
||||
sprintf(buf, "-1\n");
|
||||
}
|
||||
|
||||
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)
|
|||
else
|
||||
return -EINVAL;
|
||||
|
||||
if (((tun->owner != -1 && cred->euid != tun->owner) ||
|
||||
(tun->group != -1 && !in_egroup_p(tun->group))) &&
|
||||
if (((uid_valid(tun->owner) && !uid_eq(cred->euid, tun->owner)) ||
|
||||
(gid_valid(tun->group) && !in_egroup_p(tun->group))) &&
|
||||
!capable(CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
err = security_tun_dev_attach(tun->socket.sk);
|
||||
|
@ -1374,6 +1380,8 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
|
|||
void __user* argp = (void __user*)arg;
|
||||
struct sock_fprog fprog;
|
||||
struct ifreq ifr;
|
||||
kuid_t owner;
|
||||
kgid_t group;
|
||||
int sndbuf;
|
||||
int vnet_hdr_sz;
|
||||
int ret;
|
||||
|
@ -1447,16 +1455,26 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
|
|||
|
||||
case TUNSETOWNER:
|
||||
/* Set owner of the device */
|
||||
tun->owner = (uid_t) arg;
|
||||
|
||||
tun_debug(KERN_INFO, tun, "owner set to %d\n", tun->owner);
|
||||
owner = make_kuid(current_user_ns(), arg);
|
||||
if (!uid_valid(owner)) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
tun->owner = owner;
|
||||
tun_debug(KERN_INFO, tun, "owner set to %d\n",
|
||||
from_kuid(&init_user_ns, tun->owner));
|
||||
break;
|
||||
|
||||
case TUNSETGROUP:
|
||||
/* Set group of the device */
|
||||
tun->group= (gid_t) arg;
|
||||
|
||||
tun_debug(KERN_INFO, tun, "group set to %d\n", tun->group);
|
||||
group = make_kgid(current_user_ns(), arg);
|
||||
if (!gid_valid(group)) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
tun->group = group;
|
||||
tun_debug(KERN_INFO, tun, "group set to %d\n",
|
||||
from_kgid(&init_user_ns, tun->group));
|
||||
break;
|
||||
|
||||
case TUNSETLINK:
|
||||
|
|
|
@ -232,8 +232,10 @@ static int adhoc;
|
|||
|
||||
static int probe = 1;
|
||||
|
||||
static kuid_t proc_kuid;
|
||||
static int proc_uid /* = 0 */;
|
||||
|
||||
static kgid_t proc_kgid;
|
||||
static int proc_gid /* = 0 */;
|
||||
|
||||
static int airo_perm = 0555;
|
||||
|
@ -4499,78 +4501,79 @@ struct proc_data {
|
|||
static int setup_proc_entry( struct net_device *dev,
|
||||
struct airo_info *apriv ) {
|
||||
struct proc_dir_entry *entry;
|
||||
|
||||
/* First setup the device directory */
|
||||
strcpy(apriv->proc_name,dev->name);
|
||||
apriv->proc_entry = proc_mkdir_mode(apriv->proc_name, airo_perm,
|
||||
airo_entry);
|
||||
if (!apriv->proc_entry)
|
||||
goto fail;
|
||||
apriv->proc_entry->uid = proc_uid;
|
||||
apriv->proc_entry->gid = proc_gid;
|
||||
apriv->proc_entry->uid = proc_kuid;
|
||||
apriv->proc_entry->gid = proc_kgid;
|
||||
|
||||
/* Setup the StatsDelta */
|
||||
entry = proc_create_data("StatsDelta", S_IRUGO & proc_perm,
|
||||
apriv->proc_entry, &proc_statsdelta_ops, dev);
|
||||
if (!entry)
|
||||
goto fail_stats_delta;
|
||||
entry->uid = proc_uid;
|
||||
entry->gid = proc_gid;
|
||||
entry->uid = proc_kuid;
|
||||
entry->gid = proc_kgid;
|
||||
|
||||
/* Setup the Stats */
|
||||
entry = proc_create_data("Stats", S_IRUGO & proc_perm,
|
||||
apriv->proc_entry, &proc_stats_ops, dev);
|
||||
if (!entry)
|
||||
goto fail_stats;
|
||||
entry->uid = proc_uid;
|
||||
entry->gid = proc_gid;
|
||||
entry->uid = proc_kuid;
|
||||
entry->gid = proc_kgid;
|
||||
|
||||
/* Setup the Status */
|
||||
entry = proc_create_data("Status", S_IRUGO & proc_perm,
|
||||
apriv->proc_entry, &proc_status_ops, dev);
|
||||
if (!entry)
|
||||
goto fail_status;
|
||||
entry->uid = proc_uid;
|
||||
entry->gid = proc_gid;
|
||||
entry->uid = proc_kuid;
|
||||
entry->gid = proc_kgid;
|
||||
|
||||
/* Setup the Config */
|
||||
entry = proc_create_data("Config", proc_perm,
|
||||
apriv->proc_entry, &proc_config_ops, dev);
|
||||
if (!entry)
|
||||
goto fail_config;
|
||||
entry->uid = proc_uid;
|
||||
entry->gid = proc_gid;
|
||||
entry->uid = proc_kuid;
|
||||
entry->gid = proc_kgid;
|
||||
|
||||
/* Setup the SSID */
|
||||
entry = proc_create_data("SSID", proc_perm,
|
||||
apriv->proc_entry, &proc_SSID_ops, dev);
|
||||
if (!entry)
|
||||
goto fail_ssid;
|
||||
entry->uid = proc_uid;
|
||||
entry->gid = proc_gid;
|
||||
entry->uid = proc_kuid;
|
||||
entry->gid = proc_kgid;
|
||||
|
||||
/* Setup the APList */
|
||||
entry = proc_create_data("APList", proc_perm,
|
||||
apriv->proc_entry, &proc_APList_ops, dev);
|
||||
if (!entry)
|
||||
goto fail_aplist;
|
||||
entry->uid = proc_uid;
|
||||
entry->gid = proc_gid;
|
||||
entry->uid = proc_kuid;
|
||||
entry->gid = proc_kgid;
|
||||
|
||||
/* Setup the BSSList */
|
||||
entry = proc_create_data("BSSList", proc_perm,
|
||||
apriv->proc_entry, &proc_BSSList_ops, dev);
|
||||
if (!entry)
|
||||
goto fail_bsslist;
|
||||
entry->uid = proc_uid;
|
||||
entry->gid = proc_gid;
|
||||
entry->uid = proc_kuid;
|
||||
entry->gid = proc_kgid;
|
||||
|
||||
/* Setup the WepKey */
|
||||
entry = proc_create_data("WepKey", proc_perm,
|
||||
apriv->proc_entry, &proc_wepkey_ops, dev);
|
||||
if (!entry)
|
||||
goto fail_wepkey;
|
||||
entry->uid = proc_uid;
|
||||
entry->gid = proc_gid;
|
||||
entry->uid = proc_kuid;
|
||||
entry->gid = proc_kgid;
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -5697,11 +5700,16 @@ static int __init airo_init_module( void )
|
|||
{
|
||||
int i;
|
||||
|
||||
proc_kuid = make_kuid(&init_user_ns, proc_uid);
|
||||
proc_kgid = make_kgid(&init_user_ns, proc_gid);
|
||||
if (!uid_valid(proc_kuid) || !gid_valid(proc_kgid))
|
||||
return -EINVAL;
|
||||
|
||||
airo_entry = proc_mkdir_mode("driver/aironet", airo_perm, NULL);
|
||||
|
||||
if (airo_entry) {
|
||||
airo_entry->uid = proc_uid;
|
||||
airo_entry->gid = proc_gid;
|
||||
airo_entry->uid = proc_kuid;
|
||||
airo_entry->gid = proc_kgid;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4 && io[i] && irq[i]; i++) {
|
||||
|
|
|
@ -678,7 +678,7 @@ static inline int may_follow_link(struct path *link, struct nameidata *nd)
|
|||
|
||||
/* Allowed if owner and follower match. */
|
||||
inode = link->dentry->d_inode;
|
||||
if (current_cred()->fsuid == inode->i_uid)
|
||||
if (uid_eq(current_cred()->fsuid, inode->i_uid))
|
||||
return 0;
|
||||
|
||||
/* 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)
|
|||
return 0;
|
||||
|
||||
/* Allowed if parent directory and link owner match. */
|
||||
if (parent->i_uid == inode->i_uid)
|
||||
if (uid_eq(parent->i_uid, inode->i_uid))
|
||||
return 0;
|
||||
|
||||
path_put_conditional(link, nd);
|
||||
|
@ -757,7 +757,7 @@ static int may_linkat(struct path *link)
|
|||
/* Source inode owner (or CAP_FOWNER) can hardlink all they like,
|
||||
* otherwise, it must be a safe source.
|
||||
*/
|
||||
if (cred->fsuid == inode->i_uid || safe_hardlink_source(inode) ||
|
||||
if (uid_eq(cred->fsuid, inode->i_uid) || safe_hardlink_source(inode) ||
|
||||
capable(CAP_FOWNER))
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <linux/export.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/cred.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/page.h>
|
||||
|
@ -56,6 +57,9 @@ int seq_open(struct file *file, const struct seq_operations *op)
|
|||
memset(p, 0, sizeof(*p));
|
||||
mutex_init(&p->lock);
|
||||
p->op = op;
|
||||
#ifdef CONFIG_USER_NS
|
||||
p->user_ns = file->f_cred->user_ns;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Wrappers around seq_open(e.g. swaps_open) need to be
|
||||
|
|
|
@ -159,6 +159,7 @@ struct inet_diag_handler {
|
|||
struct inet_connection_sock;
|
||||
int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
|
||||
struct sk_buff *skb, struct inet_diag_req_v2 *req,
|
||||
struct user_namespace *user_ns,
|
||||
u32 pid, u32 seq, u16 nlmsg_flags,
|
||||
const struct nlmsghdr *unlh);
|
||||
void inet_diag_dump_icsk(struct inet_hashinfo *h, struct sk_buff *skb,
|
||||
|
|
|
@ -165,6 +165,7 @@ struct netlink_skb_parms {
|
|||
struct ucred creds; /* Skb credentials */
|
||||
__u32 pid;
|
||||
__u32 dst_group;
|
||||
struct sock *ssk;
|
||||
};
|
||||
|
||||
#define NETLINK_CB(skb) (*(struct netlink_skb_parms*)&((skb)->cb))
|
||||
|
|
|
@ -13,6 +13,7 @@ struct file;
|
|||
struct path;
|
||||
struct inode;
|
||||
struct dentry;
|
||||
struct user_namespace;
|
||||
|
||||
struct seq_file {
|
||||
char *buf;
|
||||
|
@ -25,6 +26,9 @@ struct seq_file {
|
|||
struct mutex lock;
|
||||
const struct seq_operations *op;
|
||||
int poll_event;
|
||||
#ifdef CONFIG_USER_NS
|
||||
struct user_namespace *user_ns;
|
||||
#endif
|
||||
void *private;
|
||||
};
|
||||
|
||||
|
@ -128,6 +132,16 @@ int seq_put_decimal_ull(struct seq_file *m, char delimiter,
|
|||
int seq_put_decimal_ll(struct seq_file *m, char delimiter,
|
||||
long long num);
|
||||
|
||||
static inline struct user_namespace *seq_user_ns(struct seq_file *seq)
|
||||
{
|
||||
#ifdef CONFIG_USER_NS
|
||||
return seq->user_ns;
|
||||
#else
|
||||
extern struct user_namespace init_user_ns;
|
||||
return &init_user_ns;
|
||||
#endif
|
||||
}
|
||||
|
||||
#define SEQ_START_TOKEN ((void *)1)
|
||||
/*
|
||||
* Helpers for iteration over list_head-s in seq_files
|
||||
|
|
|
@ -157,7 +157,7 @@ enum {
|
|||
typedef struct ax25_uid_assoc {
|
||||
struct hlist_node uid_node;
|
||||
atomic_t refcount;
|
||||
uid_t uid;
|
||||
kuid_t uid;
|
||||
ax25_address call;
|
||||
} ax25_uid_assoc;
|
||||
|
||||
|
@ -434,7 +434,7 @@ extern unsigned long ax25_display_timer(struct timer_list *);
|
|||
|
||||
/* ax25_uid.c */
|
||||
extern int ax25_uid_policy;
|
||||
extern ax25_uid_assoc *ax25_findbyuid(uid_t);
|
||||
extern ax25_uid_assoc *ax25_findbyuid(kuid_t);
|
||||
extern int __must_check ax25_uid_ioctl(int, struct sockaddr_ax25 *);
|
||||
extern const struct file_operations ax25_uid_fops;
|
||||
extern void ax25_uid_free(void);
|
||||
|
|
|
@ -223,7 +223,10 @@ struct ip6_flowlabel {
|
|||
struct ipv6_txoptions *opt;
|
||||
unsigned long linger;
|
||||
u8 share;
|
||||
u32 owner;
|
||||
union {
|
||||
struct pid *pid;
|
||||
kuid_t uid;
|
||||
} owner;
|
||||
unsigned long lastuse;
|
||||
unsigned long expires;
|
||||
struct net *fl_net;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#ifndef __NETNS_IPV4_H__
|
||||
#define __NETNS_IPV4_H__
|
||||
|
||||
#include <linux/uidgid.h>
|
||||
#include <net/inet_frag.h>
|
||||
|
||||
struct tcpm_hash_bucket;
|
||||
|
@ -62,7 +63,7 @@ struct netns_ipv4 {
|
|||
int sysctl_icmp_ratemask;
|
||||
int sysctl_icmp_errors_use_inbound_ifaddr;
|
||||
|
||||
unsigned int sysctl_ping_group_range[2];
|
||||
kgid_t sysctl_ping_group_range[2];
|
||||
long sysctl_tcp_mem[3];
|
||||
|
||||
atomic_t rt_genid;
|
||||
|
|
|
@ -188,7 +188,8 @@ struct tcf_proto_ops {
|
|||
|
||||
unsigned long (*get)(struct tcf_proto*, u32 handle);
|
||||
void (*put)(struct tcf_proto*, unsigned long);
|
||||
int (*change)(struct tcf_proto*, unsigned long,
|
||||
int (*change)(struct sk_buff *,
|
||||
struct tcf_proto*, unsigned long,
|
||||
u32 handle, struct nlattr **,
|
||||
unsigned long *);
|
||||
int (*delete)(struct tcf_proto*, unsigned long);
|
||||
|
|
|
@ -606,6 +606,15 @@ static inline void sk_add_bind_node(struct sock *sk,
|
|||
#define sk_for_each_bound(__sk, node, list) \
|
||||
hlist_for_each_entry(__sk, node, list, sk_bind_node)
|
||||
|
||||
static inline struct user_namespace *sk_user_ns(struct sock *sk)
|
||||
{
|
||||
/* Careful only use this in a context where these parameters
|
||||
* can not change and must all be valid, such as recvmsg from
|
||||
* userspace.
|
||||
*/
|
||||
return sk->sk_socket->file->f_cred->user_ns;
|
||||
}
|
||||
|
||||
/* Sock flags */
|
||||
enum sock_flags {
|
||||
SOCK_DEAD,
|
||||
|
@ -1670,7 +1679,7 @@ static inline void sock_graft(struct sock *sk, struct socket *parent)
|
|||
write_unlock_bh(&sk->sk_callback_lock);
|
||||
}
|
||||
|
||||
extern int sock_i_uid(struct sock *sk);
|
||||
extern kuid_t sock_i_uid(struct sock *sk);
|
||||
extern unsigned long sock_i_ino(struct sock *sk);
|
||||
|
||||
static inline struct dst_entry *
|
||||
|
|
|
@ -1510,7 +1510,8 @@ struct tcp_iter_state {
|
|||
sa_family_t family;
|
||||
enum tcp_seq_states state;
|
||||
struct sock *syn_wait_sk;
|
||||
int bucket, offset, sbucket, num, uid;
|
||||
int bucket, offset, sbucket, num;
|
||||
kuid_t uid;
|
||||
loff_t last_pos;
|
||||
};
|
||||
|
||||
|
|
19
init/Kconfig
19
init/Kconfig
|
@ -942,28 +942,12 @@ config UIDGID_CONVERTED
|
|||
depends on PROC_EVENTS = n
|
||||
|
||||
# Networking
|
||||
depends on NET = n
|
||||
depends on NET_9P = n
|
||||
depends on IPX = n
|
||||
depends on PHONET = n
|
||||
depends on NET_CLS_FLOW = n
|
||||
depends on NETFILTER_XT_MATCH_OWNER = n
|
||||
depends on NETFILTER_XT_MATCH_RECENT = n
|
||||
depends on NETFILTER_XT_TARGET_LOG = n
|
||||
depends on NETFILTER_NETLINK_LOG = n
|
||||
depends on INET = n
|
||||
depends on IPV6 = n
|
||||
depends on IP_SCTP = n
|
||||
depends on AF_RXRPC = n
|
||||
depends on LLC2 = n
|
||||
depends on NET_KEY = n
|
||||
depends on INET_DIAG = n
|
||||
depends on DNS_RESOLVER = n
|
||||
depends on AX25 = n
|
||||
depends on ATALK = n
|
||||
|
||||
# Filesystems
|
||||
depends on USB_DEVICEFS = n
|
||||
depends on USB_GADGETFS = n
|
||||
depends on USB_FUNCTIONFS = n
|
||||
depends on DEVTMPFS = n
|
||||
|
@ -1019,9 +1003,6 @@ config UIDGID_CONVERTED
|
|||
depends on !UML || HOSTFS = n
|
||||
|
||||
# The rare drivers that won't build
|
||||
depends on AIRO = n
|
||||
depends on AIRO_CS = n
|
||||
depends on TUN = n
|
||||
depends on INFINIBAND_QIB = n
|
||||
depends on BLK_DEV_LOOP = n
|
||||
depends on ANDROID_BINDER_IPC = n
|
||||
|
|
|
@ -479,6 +479,7 @@ pid_t pid_nr_ns(struct pid *pid, struct pid_namespace *ns)
|
|||
}
|
||||
return nr;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pid_nr_ns);
|
||||
|
||||
pid_t pid_vnr(struct pid *pid)
|
||||
{
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/export.h>
|
||||
|
||||
#define BITS_PER_PAGE (PAGE_SIZE*8)
|
||||
|
||||
|
@ -144,6 +145,7 @@ void free_pid_ns(struct kref *kref)
|
|||
if (parent != NULL)
|
||||
put_pid_ns(parent);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(free_pid_ns);
|
||||
|
||||
void zap_pid_ns_processes(struct pid_namespace *pid_ns)
|
||||
{
|
||||
|
|
|
@ -183,7 +183,8 @@ static int atalk_seq_socket_show(struct seq_file *seq, void *v)
|
|||
ntohs(at->dest_net), at->dest_node, at->dest_port,
|
||||
sk_wmem_alloc_get(s),
|
||||
sk_rmem_alloc_get(s),
|
||||
s->sk_state, SOCK_INODE(s->sk_socket)->i_uid);
|
||||
s->sk_state,
|
||||
from_kuid_munged(seq_user_ns(seq), sock_i_uid(s)));
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -51,14 +51,14 @@ int ax25_uid_policy;
|
|||
|
||||
EXPORT_SYMBOL(ax25_uid_policy);
|
||||
|
||||
ax25_uid_assoc *ax25_findbyuid(uid_t uid)
|
||||
ax25_uid_assoc *ax25_findbyuid(kuid_t uid)
|
||||
{
|
||||
ax25_uid_assoc *ax25_uid, *res = NULL;
|
||||
struct hlist_node *node;
|
||||
|
||||
read_lock(&ax25_uid_lock);
|
||||
ax25_uid_for_each(ax25_uid, node, &ax25_uid_list) {
|
||||
if (ax25_uid->uid == uid) {
|
||||
if (uid_eq(ax25_uid->uid, uid)) {
|
||||
ax25_uid_hold(ax25_uid);
|
||||
res = ax25_uid;
|
||||
break;
|
||||
|
@ -84,7 +84,7 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
|
|||
read_lock(&ax25_uid_lock);
|
||||
ax25_uid_for_each(ax25_uid, node, &ax25_uid_list) {
|
||||
if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0) {
|
||||
res = ax25_uid->uid;
|
||||
res = from_kuid_munged(current_user_ns(), ax25_uid->uid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -93,9 +93,14 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
|
|||
return res;
|
||||
|
||||
case SIOCAX25ADDUID:
|
||||
{
|
||||
kuid_t sax25_kuid;
|
||||
if (!capable(CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
user = ax25_findbyuid(sax->sax25_uid);
|
||||
sax25_kuid = make_kuid(current_user_ns(), sax->sax25_uid);
|
||||
if (!uid_valid(sax25_kuid))
|
||||
return -EINVAL;
|
||||
user = ax25_findbyuid(sax25_kuid);
|
||||
if (user) {
|
||||
ax25_uid_put(user);
|
||||
return -EEXIST;
|
||||
|
@ -106,7 +111,7 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
|
|||
return -ENOMEM;
|
||||
|
||||
atomic_set(&ax25_uid->refcount, 1);
|
||||
ax25_uid->uid = sax->sax25_uid;
|
||||
ax25_uid->uid = sax25_kuid;
|
||||
ax25_uid->call = sax->sax25_call;
|
||||
|
||||
write_lock(&ax25_uid_lock);
|
||||
|
@ -114,7 +119,7 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
|
|||
write_unlock(&ax25_uid_lock);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
case SIOCAX25DELUID:
|
||||
if (!capable(CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
|
@ -172,7 +177,9 @@ static int ax25_uid_seq_show(struct seq_file *seq, void *v)
|
|||
struct ax25_uid_assoc *pt;
|
||||
|
||||
pt = hlist_entry(v, struct ax25_uid_assoc, uid_node);
|
||||
seq_printf(seq, "%6d %s\n", pt->uid, ax2asc(buf, &pt->call));
|
||||
seq_printf(seq, "%6d %s\n",
|
||||
from_kuid_munged(seq_user_ns(seq), pt->uid),
|
||||
ax2asc(buf, &pt->call));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -4520,8 +4520,8 @@ static void dev_change_rx_flags(struct net_device *dev, int flags)
|
|||
static int __dev_set_promiscuity(struct net_device *dev, int inc)
|
||||
{
|
||||
unsigned int old_flags = dev->flags;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
kuid_t uid;
|
||||
kgid_t gid;
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
|
@ -4553,7 +4553,8 @@ static int __dev_set_promiscuity(struct net_device *dev, int inc)
|
|||
dev->name, (dev->flags & IFF_PROMISC),
|
||||
(old_flags & IFF_PROMISC),
|
||||
audit_get_loginuid(current),
|
||||
uid, gid,
|
||||
from_kuid(&init_user_ns, uid),
|
||||
from_kgid(&init_user_ns, gid),
|
||||
audit_get_sessionid(current));
|
||||
}
|
||||
|
||||
|
|
|
@ -45,12 +45,17 @@
|
|||
static __inline__ int scm_check_creds(struct ucred *creds)
|
||||
{
|
||||
const struct cred *cred = current_cred();
|
||||
kuid_t uid = make_kuid(cred->user_ns, creds->uid);
|
||||
kgid_t gid = make_kgid(cred->user_ns, creds->gid);
|
||||
|
||||
if (!uid_valid(uid) || !gid_valid(gid))
|
||||
return -EINVAL;
|
||||
|
||||
if ((creds->pid == task_tgid_vnr(current) || capable(CAP_SYS_ADMIN)) &&
|
||||
((creds->uid == cred->uid || creds->uid == cred->euid ||
|
||||
creds->uid == cred->suid) || capable(CAP_SETUID)) &&
|
||||
((creds->gid == cred->gid || creds->gid == cred->egid ||
|
||||
creds->gid == cred->sgid) || capable(CAP_SETGID))) {
|
||||
((uid_eq(uid, cred->uid) || uid_eq(uid, cred->euid) ||
|
||||
uid_eq(uid, cred->suid)) || capable(CAP_SETUID)) &&
|
||||
((gid_eq(gid, cred->gid) || gid_eq(gid, cred->egid) ||
|
||||
gid_eq(gid, cred->sgid)) || capable(CAP_SETGID))) {
|
||||
return 0;
|
||||
}
|
||||
return -EPERM;
|
||||
|
@ -149,6 +154,9 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p)
|
|||
goto error;
|
||||
break;
|
||||
case SCM_CREDENTIALS:
|
||||
{
|
||||
kuid_t uid;
|
||||
kgid_t gid;
|
||||
if (cmsg->cmsg_len != CMSG_LEN(sizeof(struct ucred)))
|
||||
goto error;
|
||||
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)
|
|||
p->pid = pid;
|
||||
}
|
||||
|
||||
err = -EINVAL;
|
||||
uid = make_kuid(current_user_ns(), p->creds.uid);
|
||||
gid = make_kgid(current_user_ns(), p->creds.gid);
|
||||
if (!uid_valid(uid) || !gid_valid(gid))
|
||||
goto error;
|
||||
|
||||
if (!p->cred ||
|
||||
(p->cred->euid != p->creds.uid) ||
|
||||
(p->cred->egid != p->creds.gid)) {
|
||||
!uid_eq(p->cred->euid, uid) ||
|
||||
!gid_eq(p->cred->egid, gid)) {
|
||||
struct cred *cred;
|
||||
err = -ENOMEM;
|
||||
cred = prepare_creds();
|
||||
if (!cred)
|
||||
goto error;
|
||||
|
||||
cred->uid = cred->euid = p->creds.uid;
|
||||
cred->gid = cred->egid = p->creds.gid;
|
||||
cred->uid = cred->euid = uid;
|
||||
cred->gid = cred->egid = gid;
|
||||
if (p->cred)
|
||||
put_cred(p->cred);
|
||||
p->cred = cred;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
|
|
|
@ -868,8 +868,8 @@ void cred_to_ucred(struct pid *pid, const struct cred *cred,
|
|||
if (cred) {
|
||||
struct user_namespace *current_ns = current_user_ns();
|
||||
|
||||
ucred->uid = from_kuid(current_ns, cred->euid);
|
||||
ucred->gid = from_kgid(current_ns, cred->egid);
|
||||
ucred->uid = from_kuid_munged(current_ns, cred->euid);
|
||||
ucred->gid = from_kgid_munged(current_ns, cred->egid);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cred_to_ucred);
|
||||
|
@ -1527,12 +1527,12 @@ void sock_edemux(struct sk_buff *skb)
|
|||
}
|
||||
EXPORT_SYMBOL(sock_edemux);
|
||||
|
||||
int sock_i_uid(struct sock *sk)
|
||||
kuid_t sock_i_uid(struct sock *sk)
|
||||
{
|
||||
int uid;
|
||||
kuid_t uid;
|
||||
|
||||
read_lock_bh(&sk->sk_callback_lock);
|
||||
uid = sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_uid : 0;
|
||||
uid = sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_uid : GLOBAL_ROOT_UID;
|
||||
read_unlock_bh(&sk->sk_callback_lock);
|
||||
return uid;
|
||||
}
|
||||
|
|
|
@ -69,6 +69,7 @@ static inline void inet_diag_unlock_handler(
|
|||
|
||||
int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
|
||||
struct sk_buff *skb, struct inet_diag_req_v2 *req,
|
||||
struct user_namespace *user_ns,
|
||||
u32 pid, u32 seq, u16 nlmsg_flags,
|
||||
const struct nlmsghdr *unlh)
|
||||
{
|
||||
|
@ -124,7 +125,7 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
|
|||
}
|
||||
#endif
|
||||
|
||||
r->idiag_uid = sock_i_uid(sk);
|
||||
r->idiag_uid = from_kuid_munged(user_ns, sock_i_uid(sk));
|
||||
r->idiag_inode = sock_i_ino(sk);
|
||||
|
||||
if (ext & (1 << (INET_DIAG_MEMINFO - 1))) {
|
||||
|
@ -199,11 +200,12 @@ EXPORT_SYMBOL_GPL(inet_sk_diag_fill);
|
|||
|
||||
static int inet_csk_diag_fill(struct sock *sk,
|
||||
struct sk_buff *skb, struct inet_diag_req_v2 *req,
|
||||
struct user_namespace *user_ns,
|
||||
u32 pid, u32 seq, u16 nlmsg_flags,
|
||||
const struct nlmsghdr *unlh)
|
||||
{
|
||||
return inet_sk_diag_fill(sk, inet_csk(sk),
|
||||
skb, req, pid, seq, nlmsg_flags, unlh);
|
||||
skb, req, user_ns, pid, seq, nlmsg_flags, unlh);
|
||||
}
|
||||
|
||||
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,
|
|||
}
|
||||
|
||||
static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
|
||||
struct inet_diag_req_v2 *r, u32 pid, u32 seq, u16 nlmsg_flags,
|
||||
struct inet_diag_req_v2 *r,
|
||||
struct user_namespace *user_ns,
|
||||
u32 pid, u32 seq, u16 nlmsg_flags,
|
||||
const struct nlmsghdr *unlh)
|
||||
{
|
||||
if (sk->sk_state == TCP_TIME_WAIT)
|
||||
return inet_twsk_diag_fill((struct inet_timewait_sock *)sk,
|
||||
skb, r, pid, seq, nlmsg_flags,
|
||||
unlh);
|
||||
return inet_csk_diag_fill(sk, skb, r, pid, seq, nlmsg_flags, unlh);
|
||||
return inet_csk_diag_fill(sk, skb, r, user_ns, pid, seq, nlmsg_flags, unlh);
|
||||
}
|
||||
|
||||
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
|
|||
}
|
||||
|
||||
err = sk_diag_fill(sk, rep, req,
|
||||
sk_user_ns(NETLINK_CB(in_skb).ssk),
|
||||
NETLINK_CB(in_skb).pid,
|
||||
nlh->nlmsg_seq, 0, nlh);
|
||||
if (err < 0) {
|
||||
|
@ -551,6 +556,7 @@ static int inet_csk_diag_dump(struct sock *sk,
|
|||
return 0;
|
||||
|
||||
return inet_csk_diag_fill(sk, skb, r,
|
||||
sk_user_ns(NETLINK_CB(cb->skb).ssk),
|
||||
NETLINK_CB(cb->skb).pid,
|
||||
cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh);
|
||||
}
|
||||
|
@ -591,7 +597,9 @@ static int inet_twsk_diag_dump(struct inet_timewait_sock *tw,
|
|||
}
|
||||
|
||||
static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk,
|
||||
struct request_sock *req, u32 pid, u32 seq,
|
||||
struct request_sock *req,
|
||||
struct user_namespace *user_ns,
|
||||
u32 pid, u32 seq,
|
||||
const struct nlmsghdr *unlh)
|
||||
{
|
||||
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,
|
|||
r->idiag_expires = jiffies_to_msecs(tmo);
|
||||
r->idiag_rqueue = 0;
|
||||
r->idiag_wqueue = 0;
|
||||
r->idiag_uid = sock_i_uid(sk);
|
||||
r->idiag_uid = from_kuid_munged(user_ns, sock_i_uid(sk));
|
||||
r->idiag_inode = 0;
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
if (r->idiag_family == AF_INET6) {
|
||||
|
@ -702,6 +710,7 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk,
|
|||
}
|
||||
|
||||
err = inet_diag_fill_req(skb, sk, req,
|
||||
sk_user_ns(NETLINK_CB(cb->skb).ssk),
|
||||
NETLINK_CB(cb->skb).pid,
|
||||
cb->nlh->nlmsg_seq, cb->nlh);
|
||||
if (err < 0) {
|
||||
|
|
|
@ -185,10 +185,10 @@ exit:
|
|||
return sk;
|
||||
}
|
||||
|
||||
static void inet_get_ping_group_range_net(struct net *net, gid_t *low,
|
||||
gid_t *high)
|
||||
static void inet_get_ping_group_range_net(struct net *net, kgid_t *low,
|
||||
kgid_t *high)
|
||||
{
|
||||
gid_t *data = net->ipv4.sysctl_ping_group_range;
|
||||
kgid_t *data = net->ipv4.sysctl_ping_group_range;
|
||||
unsigned int seq;
|
||||
|
||||
do {
|
||||
|
@ -203,19 +203,13 @@ static void inet_get_ping_group_range_net(struct net *net, gid_t *low,
|
|||
static int ping_init_sock(struct sock *sk)
|
||||
{
|
||||
struct net *net = sock_net(sk);
|
||||
gid_t group = current_egid();
|
||||
gid_t range[2];
|
||||
kgid_t group = current_egid();
|
||||
struct group_info *group_info = get_current_groups();
|
||||
int i, j, count = group_info->ngroups;
|
||||
kgid_t low, high;
|
||||
|
||||
inet_get_ping_group_range_net(net, range, range+1);
|
||||
low = make_kgid(&init_user_ns, range[0]);
|
||||
high = make_kgid(&init_user_ns, range[1]);
|
||||
if (!gid_valid(low) || !gid_valid(high) || gid_lt(high, low))
|
||||
return -EACCES;
|
||||
|
||||
if (range[0] <= group && group <= range[1])
|
||||
inet_get_ping_group_range_net(net, &low, &high);
|
||||
if (gid_lte(low, group) && gid_lte(group, high))
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < group_info->nblocks; i++) {
|
||||
|
@ -845,7 +839,9 @@ static void ping_format_sock(struct sock *sp, struct seq_file *f,
|
|||
bucket, src, srcp, dest, destp, sp->sk_state,
|
||||
sk_wmem_alloc_get(sp),
|
||||
sk_rmem_alloc_get(sp),
|
||||
0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp),
|
||||
0, 0L, 0,
|
||||
from_kuid_munged(seq_user_ns(f), sock_i_uid(sp)),
|
||||
0, sock_i_ino(sp),
|
||||
atomic_read(&sp->sk_refcnt), sp,
|
||||
atomic_read(&sp->sk_drops), len);
|
||||
}
|
||||
|
|
|
@ -992,7 +992,9 @@ static void raw_sock_seq_show(struct seq_file *seq, struct sock *sp, int i)
|
|||
i, src, srcp, dest, destp, sp->sk_state,
|
||||
sk_wmem_alloc_get(sp),
|
||||
sk_rmem_alloc_get(sp),
|
||||
0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp),
|
||||
0, 0L, 0,
|
||||
from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)),
|
||||
0, sock_i_ino(sp),
|
||||
atomic_read(&sp->sk_refcnt), sp, atomic_read(&sp->sk_drops));
|
||||
}
|
||||
|
||||
|
|
|
@ -76,9 +76,9 @@ static int ipv4_local_port_range(ctl_table *table, int write,
|
|||
}
|
||||
|
||||
|
||||
static void inet_get_ping_group_range_table(struct ctl_table *table, gid_t *low, gid_t *high)
|
||||
static void inet_get_ping_group_range_table(struct ctl_table *table, kgid_t *low, kgid_t *high)
|
||||
{
|
||||
gid_t *data = table->data;
|
||||
kgid_t *data = table->data;
|
||||
unsigned int seq;
|
||||
do {
|
||||
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,
|
|||
}
|
||||
|
||||
/* Update system visible IP port range */
|
||||
static void set_ping_group_range(struct ctl_table *table, gid_t range[2])
|
||||
static void set_ping_group_range(struct ctl_table *table, kgid_t low, kgid_t high)
|
||||
{
|
||||
gid_t *data = table->data;
|
||||
kgid_t *data = table->data;
|
||||
write_seqlock(&sysctl_local_ports.lock);
|
||||
data[0] = range[0];
|
||||
data[1] = range[1];
|
||||
data[0] = low;
|
||||
data[1] = high;
|
||||
write_sequnlock(&sysctl_local_ports.lock);
|
||||
}
|
||||
|
||||
|
@ -103,21 +103,33 @@ static int ipv4_ping_group_range(ctl_table *table, int write,
|
|||
void __user *buffer,
|
||||
size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
struct user_namespace *user_ns = current_user_ns();
|
||||
int ret;
|
||||
gid_t range[2];
|
||||
gid_t urange[2];
|
||||
kgid_t low, high;
|
||||
ctl_table tmp = {
|
||||
.data = &range,
|
||||
.maxlen = sizeof(range),
|
||||
.data = &urange,
|
||||
.maxlen = sizeof(urange),
|
||||
.mode = table->mode,
|
||||
.extra1 = &ip_ping_group_range_min,
|
||||
.extra2 = &ip_ping_group_range_max,
|
||||
};
|
||||
|
||||
inet_get_ping_group_range_table(table, range, range + 1);
|
||||
inet_get_ping_group_range_table(table, &low, &high);
|
||||
urange[0] = from_kgid_munged(user_ns, low);
|
||||
urange[1] = from_kgid_munged(user_ns, high);
|
||||
ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
|
||||
|
||||
if (write && ret == 0)
|
||||
set_ping_group_range(table, range);
|
||||
if (write && ret == 0) {
|
||||
low = make_kgid(user_ns, urange[0]);
|
||||
high = make_kgid(user_ns, urange[1]);
|
||||
if (!gid_valid(low) || !gid_valid(high) ||
|
||||
(urange[1] < urange[0]) || gid_lt(high, low)) {
|
||||
low = make_kgid(&init_user_ns, 1);
|
||||
high = make_kgid(&init_user_ns, 0);
|
||||
}
|
||||
set_ping_group_range(table, low, high);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -786,7 +798,7 @@ static struct ctl_table ipv4_net_table[] = {
|
|||
{
|
||||
.procname = "ping_group_range",
|
||||
.data = &init_net.ipv4.sysctl_ping_group_range,
|
||||
.maxlen = sizeof(init_net.ipv4.sysctl_ping_group_range),
|
||||
.maxlen = sizeof(gid_t)*2,
|
||||
.mode = 0644,
|
||||
.proc_handler = ipv4_ping_group_range,
|
||||
},
|
||||
|
@ -830,8 +842,8 @@ static __net_init int ipv4_sysctl_init_net(struct net *net)
|
|||
* Sane defaults - nobody may create ping sockets.
|
||||
* Boot scripts should set this to distro-specific group.
|
||||
*/
|
||||
net->ipv4.sysctl_ping_group_range[0] = 1;
|
||||
net->ipv4.sysctl_ping_group_range[1] = 0;
|
||||
net->ipv4.sysctl_ping_group_range[0] = make_kgid(&init_user_ns, 1);
|
||||
net->ipv4.sysctl_ping_group_range[1] = make_kgid(&init_user_ns, 0);
|
||||
|
||||
tcp_init_mem(net);
|
||||
|
||||
|
|
|
@ -2393,7 +2393,7 @@ void tcp_proc_unregister(struct net *net, struct tcp_seq_afinfo *afinfo)
|
|||
EXPORT_SYMBOL(tcp_proc_unregister);
|
||||
|
||||
static void get_openreq4(const struct sock *sk, const struct request_sock *req,
|
||||
struct seq_file *f, int i, int uid, int *len)
|
||||
struct seq_file *f, int i, kuid_t uid, int *len)
|
||||
{
|
||||
const struct inet_request_sock *ireq = inet_rsk(req);
|
||||
long delta = req->expires - jiffies;
|
||||
|
@ -2410,7 +2410,7 @@ static void get_openreq4(const struct sock *sk, const struct request_sock *req,
|
|||
1, /* timers active (only the expire timer) */
|
||||
jiffies_delta_to_clock_t(delta),
|
||||
req->retrans,
|
||||
uid,
|
||||
from_kuid_munged(seq_user_ns(f), uid),
|
||||
0, /* non standard timer */
|
||||
0, /* open_requests have no inode */
|
||||
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)
|
|||
timer_active,
|
||||
jiffies_delta_to_clock_t(timer_expires - jiffies),
|
||||
icsk->icsk_retransmits,
|
||||
sock_i_uid(sk),
|
||||
from_kuid_munged(seq_user_ns(f), sock_i_uid(sk)),
|
||||
icsk->icsk_probes_out,
|
||||
sock_i_ino(sk),
|
||||
atomic_read(&sk->sk_refcnt), sk,
|
||||
|
|
|
@ -2110,7 +2110,9 @@ static void udp4_format_sock(struct sock *sp, struct seq_file *f,
|
|||
bucket, src, srcp, dest, destp, sp->sk_state,
|
||||
sk_wmem_alloc_get(sp),
|
||||
sk_rmem_alloc_get(sp),
|
||||
0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp),
|
||||
0, 0L, 0,
|
||||
from_kuid_munged(seq_user_ns(f), sock_i_uid(sp)),
|
||||
0, sock_i_ino(sp),
|
||||
atomic_read(&sp->sk_refcnt), sp,
|
||||
atomic_read(&sp->sk_drops), len);
|
||||
}
|
||||
|
|
|
@ -24,7 +24,9 @@ static int sk_diag_dump(struct sock *sk, struct sk_buff *skb,
|
|||
if (!inet_diag_bc_sk(bc, sk))
|
||||
return 0;
|
||||
|
||||
return inet_sk_diag_fill(sk, NULL, skb, req, NETLINK_CB(cb->skb).pid,
|
||||
return inet_sk_diag_fill(sk, NULL, skb, req,
|
||||
sk_user_ns(NETLINK_CB(cb->skb).ssk),
|
||||
NETLINK_CB(cb->skb).pid,
|
||||
cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh);
|
||||
}
|
||||
|
||||
|
@ -69,6 +71,7 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb,
|
|||
goto out;
|
||||
|
||||
err = inet_sk_diag_fill(sk, NULL, rep, req,
|
||||
sk_user_ns(NETLINK_CB(in_skb).ssk),
|
||||
NETLINK_CB(in_skb).pid,
|
||||
nlh->nlmsg_seq, 0, nlh);
|
||||
if (err < 0) {
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <linux/seq_file.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/pid_namespace.h>
|
||||
|
||||
#include <net/net_namespace.h>
|
||||
#include <net/sock.h>
|
||||
|
@ -91,6 +92,8 @@ static struct ip6_flowlabel *fl_lookup(struct net *net, __be32 label)
|
|||
static void fl_free(struct ip6_flowlabel *fl)
|
||||
{
|
||||
if (fl) {
|
||||
if (fl->share == IPV6_FL_S_PROCESS)
|
||||
put_pid(fl->owner.pid);
|
||||
release_net(fl->fl_net);
|
||||
kfree(fl->opt);
|
||||
}
|
||||
|
@ -394,10 +397,10 @@ fl_create(struct net *net, struct sock *sk, struct in6_flowlabel_req *freq,
|
|||
case IPV6_FL_S_ANY:
|
||||
break;
|
||||
case IPV6_FL_S_PROCESS:
|
||||
fl->owner = current->pid;
|
||||
fl->owner.pid = get_task_pid(current, PIDTYPE_PID);
|
||||
break;
|
||||
case IPV6_FL_S_USER:
|
||||
fl->owner = current_euid();
|
||||
fl->owner.uid = current_euid();
|
||||
break;
|
||||
default:
|
||||
err = -EINVAL;
|
||||
|
@ -561,7 +564,10 @@ recheck:
|
|||
err = -EPERM;
|
||||
if (fl1->share == IPV6_FL_S_EXCL ||
|
||||
fl1->share != fl->share ||
|
||||
fl1->owner != fl->owner)
|
||||
((fl1->share == IPV6_FL_S_PROCESS) &&
|
||||
(fl1->owner.pid == fl->owner.pid)) ||
|
||||
((fl1->share == IPV6_FL_S_USER) &&
|
||||
uid_eq(fl1->owner.uid, fl->owner.uid)))
|
||||
goto release;
|
||||
|
||||
err = -EINVAL;
|
||||
|
@ -621,6 +627,7 @@ done:
|
|||
|
||||
struct ip6fl_iter_state {
|
||||
struct seq_net_private p;
|
||||
struct pid_namespace *pid_ns;
|
||||
int bucket;
|
||||
};
|
||||
|
||||
|
@ -699,6 +706,7 @@ static void ip6fl_seq_stop(struct seq_file *seq, void *v)
|
|||
|
||||
static int ip6fl_seq_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
struct ip6fl_iter_state *state = ip6fl_seq_private(seq);
|
||||
if (v == SEQ_START_TOKEN)
|
||||
seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-32s %s\n",
|
||||
"Label", "S", "Owner", "Users", "Linger", "Expires", "Dst", "Opt");
|
||||
|
@ -708,7 +716,11 @@ static int ip6fl_seq_show(struct seq_file *seq, void *v)
|
|||
"%05X %-1d %-6d %-6d %-6ld %-8ld %pi6 %-4d\n",
|
||||
(unsigned int)ntohl(fl->label),
|
||||
fl->share,
|
||||
(int)fl->owner,
|
||||
((fl->share == IPV6_FL_S_PROCESS) ?
|
||||
pid_nr_ns(fl->owner.pid, state->pid_ns) :
|
||||
((fl->share == IPV6_FL_S_USER) ?
|
||||
from_kuid_munged(seq_user_ns(seq), fl->owner.uid) :
|
||||
0)),
|
||||
atomic_read(&fl->users),
|
||||
fl->linger/HZ,
|
||||
(long)(fl->expires - jiffies)/HZ,
|
||||
|
@ -727,8 +739,29 @@ static const struct seq_operations ip6fl_seq_ops = {
|
|||
|
||||
static int ip6fl_seq_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return seq_open_net(inode, file, &ip6fl_seq_ops,
|
||||
sizeof(struct ip6fl_iter_state));
|
||||
struct seq_file *seq;
|
||||
struct ip6fl_iter_state *state;
|
||||
int err;
|
||||
|
||||
err = seq_open_net(inode, file, &ip6fl_seq_ops,
|
||||
sizeof(struct ip6fl_iter_state));
|
||||
|
||||
if (!err) {
|
||||
seq = file->private_data;
|
||||
state = ip6fl_seq_private(seq);
|
||||
rcu_read_lock();
|
||||
state->pid_ns = get_pid_ns(task_active_pid_ns(current));
|
||||
rcu_read_unlock();
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ip6fl_seq_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct seq_file *seq = file->private_data;
|
||||
struct ip6fl_iter_state *state = ip6fl_seq_private(seq);
|
||||
put_pid_ns(state->pid_ns);
|
||||
return seq_release_net(inode, file);
|
||||
}
|
||||
|
||||
static const struct file_operations ip6fl_seq_fops = {
|
||||
|
@ -736,7 +769,7 @@ static const struct file_operations ip6fl_seq_fops = {
|
|||
.open = ip6fl_seq_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = seq_release_net,
|
||||
.release = ip6fl_seq_release,
|
||||
};
|
||||
|
||||
static int __net_init ip6_flowlabel_proc_init(struct net *net)
|
||||
|
|
|
@ -1251,7 +1251,8 @@ static void raw6_sock_seq_show(struct seq_file *seq, struct sock *sp, int i)
|
|||
sk_wmem_alloc_get(sp),
|
||||
sk_rmem_alloc_get(sp),
|
||||
0, 0L, 0,
|
||||
sock_i_uid(sp), 0,
|
||||
from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)),
|
||||
0,
|
||||
sock_i_ino(sp),
|
||||
atomic_read(&sp->sk_refcnt), sp, atomic_read(&sp->sk_drops));
|
||||
}
|
||||
|
|
|
@ -1828,7 +1828,7 @@ static void tcp_v6_destroy_sock(struct sock *sk)
|
|||
#ifdef CONFIG_PROC_FS
|
||||
/* Proc filesystem TCPv6 sock list dumping. */
|
||||
static void get_openreq6(struct seq_file *seq,
|
||||
const struct sock *sk, struct request_sock *req, int i, int uid)
|
||||
const struct sock *sk, struct request_sock *req, int i, kuid_t uid)
|
||||
{
|
||||
int ttd = req->expires - jiffies;
|
||||
const struct in6_addr *src = &inet6_rsk(req)->loc_addr;
|
||||
|
@ -1852,7 +1852,7 @@ static void get_openreq6(struct seq_file *seq,
|
|||
1, /* timers active (only the expire timer) */
|
||||
jiffies_to_clock_t(ttd),
|
||||
req->retrans,
|
||||
uid,
|
||||
from_kuid_munged(seq_user_ns(seq), uid),
|
||||
0, /* non standard timer */
|
||||
0, /* open_requests have no inode */
|
||||
0, req);
|
||||
|
@ -1902,7 +1902,7 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
|
|||
timer_active,
|
||||
jiffies_delta_to_clock_t(timer_expires - jiffies),
|
||||
icsk->icsk_retransmits,
|
||||
sock_i_uid(sp),
|
||||
from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)),
|
||||
icsk->icsk_probes_out,
|
||||
sock_i_ino(sp),
|
||||
atomic_read(&sp->sk_refcnt), sp,
|
||||
|
|
|
@ -1458,7 +1458,8 @@ static void udp6_sock_seq_show(struct seq_file *seq, struct sock *sp, int bucket
|
|||
sk_wmem_alloc_get(sp),
|
||||
sk_rmem_alloc_get(sp),
|
||||
0, 0L, 0,
|
||||
sock_i_uid(sp), 0,
|
||||
from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)),
|
||||
0,
|
||||
sock_i_ino(sp),
|
||||
atomic_read(&sp->sk_refcnt), sp,
|
||||
atomic_read(&sp->sk_drops));
|
||||
|
|
|
@ -217,7 +217,8 @@ static int ipx_seq_socket_show(struct seq_file *seq, void *v)
|
|||
seq_printf(seq, "%08X %08X %02X %03d\n",
|
||||
sk_wmem_alloc_get(s),
|
||||
sk_rmem_alloc_get(s),
|
||||
s->sk_state, SOCK_INODE(s->sk_socket)->i_uid);
|
||||
s->sk_state,
|
||||
from_kuid_munged(seq_user_ns(seq), sock_i_uid(s)));
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -3661,7 +3661,7 @@ static int pfkey_seq_show(struct seq_file *f, void *v)
|
|||
atomic_read(&s->sk_refcnt),
|
||||
sk_rmem_alloc_get(s),
|
||||
sk_wmem_alloc_get(s),
|
||||
sock_i_uid(s),
|
||||
from_kuid_munged(seq_user_ns(f), sock_i_uid(s)),
|
||||
sock_i_ino(s)
|
||||
);
|
||||
return 0;
|
||||
|
|
|
@ -151,7 +151,7 @@ static int llc_seq_socket_show(struct seq_file *seq, void *v)
|
|||
sk_wmem_alloc_get(sk),
|
||||
sk_rmem_alloc_get(sk) - llc->copied_seq,
|
||||
sk->sk_state,
|
||||
sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_uid : -1,
|
||||
from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)),
|
||||
llc->link);
|
||||
out:
|
||||
return 0;
|
||||
|
|
|
@ -55,6 +55,7 @@ struct nfulnl_instance {
|
|||
unsigned int qlen; /* number of nlmsgs in skb */
|
||||
struct sk_buff *skb; /* pre-allocatd skb */
|
||||
struct timer_list timer;
|
||||
struct user_namespace *peer_user_ns; /* User namespace of the peer process */
|
||||
int peer_pid; /* PID of the peer process */
|
||||
|
||||
/* configurable parameters */
|
||||
|
@ -132,7 +133,7 @@ instance_put(struct nfulnl_instance *inst)
|
|||
static void nfulnl_timer(unsigned long data);
|
||||
|
||||
static struct nfulnl_instance *
|
||||
instance_create(u_int16_t group_num, int pid)
|
||||
instance_create(u_int16_t group_num, int pid, struct user_namespace *user_ns)
|
||||
{
|
||||
struct nfulnl_instance *inst;
|
||||
int err;
|
||||
|
@ -162,6 +163,7 @@ instance_create(u_int16_t group_num, int pid)
|
|||
|
||||
setup_timer(&inst->timer, nfulnl_timer, (unsigned long)inst);
|
||||
|
||||
inst->peer_user_ns = user_ns;
|
||||
inst->peer_pid = pid;
|
||||
inst->group_num = group_num;
|
||||
|
||||
|
@ -503,8 +505,11 @@ __build_packet_message(struct nfulnl_instance *inst,
|
|||
read_lock_bh(&skb->sk->sk_callback_lock);
|
||||
if (skb->sk->sk_socket && skb->sk->sk_socket->file) {
|
||||
struct file *file = skb->sk->sk_socket->file;
|
||||
__be32 uid = htonl(file->f_cred->fsuid);
|
||||
__be32 gid = htonl(file->f_cred->fsgid);
|
||||
__be32 uid = htonl(from_kuid_munged(inst->peer_user_ns,
|
||||
file->f_cred->fsuid));
|
||||
__be32 gid = htonl(from_kgid_munged(inst->peer_user_ns,
|
||||
file->f_cred->fsgid));
|
||||
/* need to unlock here since NLA_PUT may goto */
|
||||
read_unlock_bh(&skb->sk->sk_callback_lock);
|
||||
if (nla_put_be32(inst->skb, NFULA_UID, uid) ||
|
||||
nla_put_be32(inst->skb, NFULA_GID, gid))
|
||||
|
@ -783,7 +788,8 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
|
|||
}
|
||||
|
||||
inst = instance_create(group_num,
|
||||
NETLINK_CB(skb).pid);
|
||||
NETLINK_CB(skb).pid,
|
||||
sk_user_ns(NETLINK_CB(skb).ssk));
|
||||
if (IS_ERR(inst)) {
|
||||
ret = PTR_ERR(inst);
|
||||
goto out;
|
||||
|
|
|
@ -363,10 +363,12 @@ static void dump_ipv4_packet(struct sbuff *m,
|
|||
/* Max length: 15 "UID=4294967295 " */
|
||||
if ((logflags & XT_LOG_UID) && !iphoff && skb->sk) {
|
||||
read_lock_bh(&skb->sk->sk_callback_lock);
|
||||
if (skb->sk->sk_socket && skb->sk->sk_socket->file)
|
||||
if (skb->sk->sk_socket && skb->sk->sk_socket->file) {
|
||||
const struct cred *cred = skb->sk->sk_socket->file->f_cred;
|
||||
sb_add(m, "UID=%u GID=%u ",
|
||||
skb->sk->sk_socket->file->f_cred->fsuid,
|
||||
skb->sk->sk_socket->file->f_cred->fsgid);
|
||||
from_kuid_munged(&init_user_ns, cred->fsuid),
|
||||
from_kgid_munged(&init_user_ns, cred->fsgid));
|
||||
}
|
||||
read_unlock_bh(&skb->sk->sk_callback_lock);
|
||||
}
|
||||
|
||||
|
@ -719,10 +721,12 @@ static void dump_ipv6_packet(struct sbuff *m,
|
|||
/* Max length: 15 "UID=4294967295 " */
|
||||
if ((logflags & XT_LOG_UID) && recurse && skb->sk) {
|
||||
read_lock_bh(&skb->sk->sk_callback_lock);
|
||||
if (skb->sk->sk_socket && skb->sk->sk_socket->file)
|
||||
if (skb->sk->sk_socket && skb->sk->sk_socket->file) {
|
||||
const struct cred *cred = skb->sk->sk_socket->file->f_cred;
|
||||
sb_add(m, "UID=%u GID=%u ",
|
||||
skb->sk->sk_socket->file->f_cred->fsuid,
|
||||
skb->sk->sk_socket->file->f_cred->fsgid);
|
||||
from_kuid_munged(&init_user_ns, cred->fsuid),
|
||||
from_kgid_munged(&init_user_ns, cred->fsgid));
|
||||
}
|
||||
read_unlock_bh(&skb->sk->sk_callback_lock);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,17 @@
|
|||
#include <linux/netfilter/x_tables.h>
|
||||
#include <linux/netfilter/xt_owner.h>
|
||||
|
||||
static int owner_check(const struct xt_mtchk_param *par)
|
||||
{
|
||||
struct xt_owner_match_info *info = par->matchinfo;
|
||||
|
||||
/* For now only allow adding matches from the initial user namespace */
|
||||
if ((info->match & (XT_OWNER_UID|XT_OWNER_GID)) &&
|
||||
(current_user_ns() != &init_user_ns))
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
owner_mt(const struct sk_buff *skb, struct xt_action_param *par)
|
||||
{
|
||||
|
@ -37,17 +48,23 @@ owner_mt(const struct sk_buff *skb, struct xt_action_param *par)
|
|||
return ((info->match ^ info->invert) &
|
||||
(XT_OWNER_UID | XT_OWNER_GID)) == 0;
|
||||
|
||||
if (info->match & XT_OWNER_UID)
|
||||
if ((filp->f_cred->fsuid >= info->uid_min &&
|
||||
filp->f_cred->fsuid <= info->uid_max) ^
|
||||
if (info->match & XT_OWNER_UID) {
|
||||
kuid_t uid_min = make_kuid(&init_user_ns, info->uid_min);
|
||||
kuid_t uid_max = make_kuid(&init_user_ns, info->uid_max);
|
||||
if ((uid_gte(filp->f_cred->fsuid, uid_min) &&
|
||||
uid_lte(filp->f_cred->fsuid, uid_max)) ^
|
||||
!(info->invert & XT_OWNER_UID))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (info->match & XT_OWNER_GID)
|
||||
if ((filp->f_cred->fsgid >= info->gid_min &&
|
||||
filp->f_cred->fsgid <= info->gid_max) ^
|
||||
if (info->match & XT_OWNER_GID) {
|
||||
kgid_t gid_min = make_kgid(&init_user_ns, info->gid_min);
|
||||
kgid_t gid_max = make_kgid(&init_user_ns, info->gid_max);
|
||||
if ((gid_gte(filp->f_cred->fsgid, gid_min) &&
|
||||
gid_lte(filp->f_cred->fsgid, gid_max)) ^
|
||||
!(info->invert & XT_OWNER_GID))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -56,6 +73,7 @@ static struct xt_match owner_mt_reg __read_mostly = {
|
|||
.name = "owner",
|
||||
.revision = 1,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.checkentry = owner_check,
|
||||
.match = owner_mt,
|
||||
.matchsize = sizeof(struct xt_owner_match_info),
|
||||
.hooks = (1 << NF_INET_LOCAL_OUT) |
|
||||
|
|
|
@ -317,6 +317,8 @@ static int recent_mt_check(const struct xt_mtchk_param *par,
|
|||
struct recent_table *t;
|
||||
#ifdef CONFIG_PROC_FS
|
||||
struct proc_dir_entry *pde;
|
||||
kuid_t uid;
|
||||
kgid_t gid;
|
||||
#endif
|
||||
unsigned int i;
|
||||
int ret = -EINVAL;
|
||||
|
@ -372,6 +374,13 @@ static int recent_mt_check(const struct xt_mtchk_param *par,
|
|||
for (i = 0; i < ip_list_hash_size; i++)
|
||||
INIT_LIST_HEAD(&t->iphash[i]);
|
||||
#ifdef CONFIG_PROC_FS
|
||||
uid = make_kuid(&init_user_ns, ip_list_uid);
|
||||
gid = make_kgid(&init_user_ns, ip_list_gid);
|
||||
if (!uid_valid(uid) || !gid_valid(gid)) {
|
||||
kfree(t);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
pde = proc_create_data(t->name, ip_list_perms, recent_net->xt_recent,
|
||||
&recent_mt_fops, t);
|
||||
if (pde == NULL) {
|
||||
|
@ -379,8 +388,8 @@ static int recent_mt_check(const struct xt_mtchk_param *par,
|
|||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
pde->uid = ip_list_uid;
|
||||
pde->gid = ip_list_gid;
|
||||
pde->uid = uid;
|
||||
pde->gid = gid;
|
||||
#endif
|
||||
spin_lock_bh(&recent_lock);
|
||||
list_add_tail(&t->list, &recent_net->tables);
|
||||
|
|
|
@ -912,7 +912,8 @@ static void netlink_rcv_wake(struct sock *sk)
|
|||
wake_up_interruptible(&nlk->wait);
|
||||
}
|
||||
|
||||
static int netlink_unicast_kernel(struct sock *sk, struct sk_buff *skb)
|
||||
static int netlink_unicast_kernel(struct sock *sk, struct sk_buff *skb,
|
||||
struct sock *ssk)
|
||||
{
|
||||
int ret;
|
||||
struct netlink_sock *nlk = nlk_sk(sk);
|
||||
|
@ -921,6 +922,7 @@ static int netlink_unicast_kernel(struct sock *sk, struct sk_buff *skb)
|
|||
if (nlk->netlink_rcv != NULL) {
|
||||
ret = skb->len;
|
||||
skb_set_owner_r(skb, sk);
|
||||
NETLINK_CB(skb).ssk = ssk;
|
||||
nlk->netlink_rcv(skb);
|
||||
consume_skb(skb);
|
||||
} else {
|
||||
|
@ -947,7 +949,7 @@ retry:
|
|||
return PTR_ERR(sk);
|
||||
}
|
||||
if (netlink_is_kernel(sk))
|
||||
return netlink_unicast_kernel(sk, skb);
|
||||
return netlink_unicast_kernel(sk, skb, ssk);
|
||||
|
||||
if (sk_filter(sk, skb)) {
|
||||
err = skb->len;
|
||||
|
|
|
@ -3749,7 +3749,7 @@ static int packet_seq_show(struct seq_file *seq, void *v)
|
|||
po->ifindex,
|
||||
po->running,
|
||||
atomic_read(&s->sk_rmem_alloc),
|
||||
sock_i_uid(s),
|
||||
from_kuid_munged(seq_user_ns(seq), sock_i_uid(s)),
|
||||
sock_i_ino(s));
|
||||
}
|
||||
|
||||
|
|
|
@ -612,7 +612,8 @@ static int pn_sock_seq_show(struct seq_file *seq, void *v)
|
|||
sk->sk_protocol, pn->sobject, pn->dobject,
|
||||
pn->resource, sk->sk_state,
|
||||
sk_wmem_alloc_get(sk), sk_rmem_alloc_get(sk),
|
||||
sock_i_uid(sk), sock_i_ino(sk),
|
||||
from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)),
|
||||
sock_i_ino(sk),
|
||||
atomic_read(&sk->sk_refcnt), sk,
|
||||
atomic_read(&sk->sk_drops), &len);
|
||||
}
|
||||
|
@ -796,7 +797,8 @@ static int pn_res_seq_show(struct seq_file *seq, void *v)
|
|||
struct sock *sk = *psk;
|
||||
|
||||
seq_printf(seq, "%02X %5d %lu%n",
|
||||
(int) (psk - pnres.sk), sock_i_uid(sk),
|
||||
(int) (psk - pnres.sk),
|
||||
from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)),
|
||||
sock_i_ino(sk), &len);
|
||||
}
|
||||
seq_printf(seq, "%*s\n", 63 - len, "");
|
||||
|
|
|
@ -319,7 +319,7 @@ replay:
|
|||
}
|
||||
}
|
||||
|
||||
err = tp->ops->change(tp, cl, t->tcm_handle, tca, &fh);
|
||||
err = tp->ops->change(skb, tp, cl, t->tcm_handle, tca, &fh);
|
||||
if (err == 0) {
|
||||
if (tp_created) {
|
||||
spin_lock_bh(root_lock);
|
||||
|
|
|
@ -162,7 +162,8 @@ errout:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int basic_change(struct tcf_proto *tp, unsigned long base, u32 handle,
|
||||
static int basic_change(struct sk_buff *in_skb,
|
||||
struct tcf_proto *tp, unsigned long base, u32 handle,
|
||||
struct nlattr **tca, unsigned long *arg)
|
||||
{
|
||||
int err;
|
||||
|
|
|
@ -151,7 +151,8 @@ static const struct nla_policy cgroup_policy[TCA_CGROUP_MAX + 1] = {
|
|||
[TCA_CGROUP_EMATCHES] = { .type = NLA_NESTED },
|
||||
};
|
||||
|
||||
static int cls_cgroup_change(struct tcf_proto *tp, unsigned long base,
|
||||
static int cls_cgroup_change(struct sk_buff *in_skb,
|
||||
struct tcf_proto *tp, unsigned long base,
|
||||
u32 handle, struct nlattr **tca,
|
||||
unsigned long *arg)
|
||||
{
|
||||
|
|
|
@ -193,15 +193,19 @@ static u32 flow_get_rtclassid(const struct sk_buff *skb)
|
|||
|
||||
static u32 flow_get_skuid(const struct sk_buff *skb)
|
||||
{
|
||||
if (skb->sk && skb->sk->sk_socket && skb->sk->sk_socket->file)
|
||||
return skb->sk->sk_socket->file->f_cred->fsuid;
|
||||
if (skb->sk && skb->sk->sk_socket && skb->sk->sk_socket->file) {
|
||||
kuid_t skuid = skb->sk->sk_socket->file->f_cred->fsuid;
|
||||
return from_kuid(&init_user_ns, skuid);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 flow_get_skgid(const struct sk_buff *skb)
|
||||
{
|
||||
if (skb->sk && skb->sk->sk_socket && skb->sk->sk_socket->file)
|
||||
return skb->sk->sk_socket->file->f_cred->fsgid;
|
||||
if (skb->sk && skb->sk->sk_socket && skb->sk->sk_socket->file) {
|
||||
kgid_t skgid = skb->sk->sk_socket->file->f_cred->fsgid;
|
||||
return from_kgid(&init_user_ns, skgid);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -347,7 +351,8 @@ static const struct nla_policy flow_policy[TCA_FLOW_MAX + 1] = {
|
|||
[TCA_FLOW_PERTURB] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int flow_change(struct tcf_proto *tp, unsigned long base,
|
||||
static int flow_change(struct sk_buff *in_skb,
|
||||
struct tcf_proto *tp, unsigned long base,
|
||||
u32 handle, struct nlattr **tca,
|
||||
unsigned long *arg)
|
||||
{
|
||||
|
@ -386,6 +391,10 @@ static int flow_change(struct tcf_proto *tp, unsigned long base,
|
|||
|
||||
if (fls(keymask) - 1 > FLOW_KEY_MAX)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if ((keymask & (FLOW_KEY_SKUID|FLOW_KEY_SKGID)) &&
|
||||
sk_user_ns(NETLINK_CB(in_skb).ssk) != &init_user_ns)
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
err = tcf_exts_validate(tp, tb, tca[TCA_RATE], &e, &flow_ext_map);
|
||||
|
|
|
@ -233,7 +233,8 @@ errout:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int fw_change(struct tcf_proto *tp, unsigned long base,
|
||||
static int fw_change(struct sk_buff *in_skb,
|
||||
struct tcf_proto *tp, unsigned long base,
|
||||
u32 handle,
|
||||
struct nlattr **tca,
|
||||
unsigned long *arg)
|
||||
|
|
|
@ -427,7 +427,8 @@ errout:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int route4_change(struct tcf_proto *tp, unsigned long base,
|
||||
static int route4_change(struct sk_buff *in_skb,
|
||||
struct tcf_proto *tp, unsigned long base,
|
||||
u32 handle,
|
||||
struct nlattr **tca,
|
||||
unsigned long *arg)
|
||||
|
|
|
@ -416,7 +416,8 @@ static const struct nla_policy rsvp_policy[TCA_RSVP_MAX + 1] = {
|
|||
[TCA_RSVP_PINFO] = { .len = sizeof(struct tc_rsvp_pinfo) },
|
||||
};
|
||||
|
||||
static int rsvp_change(struct tcf_proto *tp, unsigned long base,
|
||||
static int rsvp_change(struct sk_buff *in_skb,
|
||||
struct tcf_proto *tp, unsigned long base,
|
||||
u32 handle,
|
||||
struct nlattr **tca,
|
||||
unsigned long *arg)
|
||||
|
|
|
@ -332,7 +332,8 @@ errout:
|
|||
}
|
||||
|
||||
static int
|
||||
tcindex_change(struct tcf_proto *tp, unsigned long base, u32 handle,
|
||||
tcindex_change(struct sk_buff *in_skb,
|
||||
struct tcf_proto *tp, unsigned long base, u32 handle,
|
||||
struct nlattr **tca, unsigned long *arg)
|
||||
{
|
||||
struct nlattr *opt = tca[TCA_OPTIONS];
|
||||
|
|
|
@ -544,7 +544,8 @@ errout:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
|
||||
static int u32_change(struct sk_buff *in_skb,
|
||||
struct tcf_proto *tp, unsigned long base, u32 handle,
|
||||
struct nlattr **tca,
|
||||
unsigned long *arg)
|
||||
{
|
||||
|
|
|
@ -220,7 +220,8 @@ static int sctp_eps_seq_show(struct seq_file *seq, void *v)
|
|||
seq_printf(seq, "%8pK %8pK %-3d %-3d %-4d %-5d %5d %5lu ", ep, sk,
|
||||
sctp_sk(sk)->type, sk->sk_state, hash,
|
||||
epb->bind_addr.port,
|
||||
sock_i_uid(sk), sock_i_ino(sk));
|
||||
from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)),
|
||||
sock_i_ino(sk));
|
||||
|
||||
sctp_seq_dump_local_addrs(seq, epb);
|
||||
seq_printf(seq, "\n");
|
||||
|
@ -332,7 +333,8 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
|
|||
assoc->assoc_id,
|
||||
assoc->sndbuf_used,
|
||||
atomic_read(&assoc->rmem_alloc),
|
||||
sock_i_uid(sk), sock_i_ino(sk),
|
||||
from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)),
|
||||
sock_i_ino(sk),
|
||||
epb->bind_addr.port,
|
||||
assoc->peer.port);
|
||||
seq_printf(seq, " ");
|
||||
|
|
Загрузка…
Ссылка в новой задаче