Пример #1
0
/*
 * writing 'C' to /proc/sysrq-trigger is like sysrq-C
 */
static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf,
				   size_t count, loff_t *ppos)
{
	struct ve_struct *cur = get_exec_env();
	static int pnum = 10;

	if (count) {
		int i, cnt;
		char c[32];

		cnt = min(count, sizeof(c));
		if (copy_from_user(c, buf, cnt))
			return -EFAULT;


		for (i = 0; i < cnt && c[i] != '\n'; i++) {
			if (!ve_is_super(cur))	{
				if (!pnum)
					continue;
				printk("SysRq: CT#%u sent '%c' magic key.\n",
						cur->veid, c[i]);
				pnum--;
				continue;
			}
			__handle_sysrq(c[i], NULL, 0);
		}
	}
	return count;
}
Пример #2
0
int cpt_dump_link(struct cpt_context * ctx)
{
	struct net *net = get_exec_env()->ve_netns;
	struct net_device *dev;

	cpt_open_section(ctx, CPT_SECT_NET_DEVICE);
	for_each_netdev(net, dev) {
		struct cpt_netdev_image v;
		struct cpt_hwaddr_image hw;
		loff_t saved_obj;

		if (dev->netdev_ops->ndo_cpt == NULL) {
			eprintk_ctx("unsupported netdev %s\n", dev->name);
			cpt_close_section(ctx);
			return -EBUSY;
		}

		cpt_open_object(NULL, ctx);

		v.cpt_next = CPT_NULL;
		v.cpt_object = CPT_OBJ_NET_DEVICE;
		v.cpt_hdrlen = sizeof(v);
		v.cpt_content = CPT_CONTENT_ARRAY;

		v.cpt_index = dev->ifindex;
		v.cpt_flags = dev->flags;
		memcpy(v.cpt_name, dev->name, IFNAMSIZ);
		ctx->write(&v, sizeof(v), ctx);

		cpt_push_object(&saved_obj, ctx);

		cpt_open_object(NULL, ctx);
		dev->netdev_ops->ndo_cpt(dev, &cpt_ops, ctx);

		/* Dump hardware address */
		cpt_open_object(NULL, ctx);
		hw.cpt_next = CPT_NULL;
		hw.cpt_object = CPT_OBJ_NET_HWADDR;
		hw.cpt_hdrlen = sizeof(hw);
		hw.cpt_content = CPT_CONTENT_VOID;

		if (dev->dev_addrs.count != 1) {
			eprintk_ctx("multiple hwaddrs on %s\n", dev->name);
			return -EINVAL;
		}

		BUILD_BUG_ON(sizeof(hw.cpt_dev_addr) != MAX_ADDR_LEN);
		memcpy(hw.cpt_dev_addr, dev->dev_addr, sizeof(hw.cpt_dev_addr));
		ctx->write(&hw, sizeof(hw), ctx);
		cpt_close_object(ctx);
		
		cpt_dump_netstats(dev, ctx);

		cpt_pop_object(&saved_obj, ctx);

		cpt_close_object(ctx);
	}
	cpt_close_section(ctx);
	return 0;
}
Пример #3
0
static void sit_cpt(struct net_device *dev,
		struct cpt_ops *ops, struct cpt_context *ctx)
{
	struct cpt_tunnel_image v;
	struct ip_tunnel *t;
	struct sit_net *sitn;

	t = netdev_priv(dev);
	sitn = net_generic(get_exec_env()->ve_netns, sit_net_id);
	BUG_ON(sitn == NULL);

	v.cpt_next = CPT_NULL;
	v.cpt_object = CPT_OBJ_NET_IPIP_TUNNEL;
	v.cpt_hdrlen = sizeof(v);
	v.cpt_content = CPT_CONTENT_VOID;

	/* mark fb dev */
	v.cpt_tnl_flags = CPT_TUNNEL_SIT;
	if (dev == sitn->fb_tunnel_dev)
		v.cpt_tnl_flags |= CPT_TUNNEL_FBDEV;

	v.cpt_i_flags = t->parms.i_flags;
	v.cpt_o_flags = t->parms.o_flags;
	v.cpt_i_key = t->parms.i_key;
	v.cpt_o_key = t->parms.o_key;

	BUILD_BUG_ON(sizeof(v.cpt_iphdr) != sizeof(t->parms.iph));
	memcpy(&v.cpt_iphdr, &t->parms.iph, sizeof(t->parms.iph));

	ops->write(&v, sizeof(v), ctx);
}
Пример #4
0
/*
 * The higher levels take care of making this non-reentrant (it's
 * called with bh's disabled).
 */
static netdev_tx_t loopback_xmit(struct sk_buff *skb,
				 struct net_device *dev)
{
	struct pcpu_lstats *pcpu_lstats, *lb_stats;
	int len;

#ifdef CONFIG_VE
	if (unlikely(get_exec_env()->disable_net)) {
		kfree_skb(skb);
		return 0;
	}
#endif
	skb_orphan(skb);

	skb->protocol = eth_type_trans(skb, dev);

	/* it's OK to use per_cpu_ptr() because BHs are off */
	pcpu_lstats = dev->ml_priv;
	lb_stats = per_cpu_ptr(pcpu_lstats, smp_processor_id());

	len = skb->len;
	if (likely(netif_rx(skb) == NET_RX_SUCCESS)) {
		lb_stats->bytes += len;
		lb_stats->packets++;
	} else
		lb_stats->drops++;

	return NETDEV_TX_OK;
}
Пример #5
0
static void ve_stop(void *data)
{
	struct ve_struct *ve;
	int event = VE_EVENT_STOP;

	if (test_and_clear_bit(VE_REBOOT, &get_exec_env()->flags) &&
		reboot_event)
		event = VE_EVENT_REBOOT;

	ve = (struct ve_struct *)data;
	vzevent_send(event, "%d", ve->veid);
}
Пример #6
0
void vlan_setup(struct net_device *dev)
{
	ether_setup(dev);

	dev->priv_flags		|= IFF_802_1Q_VLAN;
	dev->priv_flags		&= ~IFF_XMIT_DST_RELEASE;
	dev->tx_queue_len	= 0;

	dev->netdev_ops		= &vlan_netdev_ops;
	dev->destructor		= free_netdev;
	dev->ethtool_ops	= &vlan_ethtool_ops;

	memset(dev->broadcast, 0, ETH_ALEN);
	if (!ve_is_super(get_exec_env()))
		dev->features |= NETIF_F_VIRTUAL;
}
Пример #7
0
static int sit_init_net(struct net *net)
{
	int err;
	struct sit_net *sitn;

	if (!(get_exec_env()->features & VE_FEATURE_SIT))
		return 0;

	err = -ENOMEM;
	sitn = kzalloc(sizeof(struct sit_net), GFP_KERNEL);
	if (sitn == NULL)
		goto err_alloc;

	err = net_assign_generic(net, sit_net_id, sitn);
	if (err < 0)
		goto err_assign;

	sitn->tunnels[0] = sitn->tunnels_wc;
	sitn->tunnels[1] = sitn->tunnels_l;
	sitn->tunnels[2] = sitn->tunnels_r;
	sitn->tunnels[3] = sitn->tunnels_r_l;

	sitn->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "sit0",
					   ipip6_tunnel_setup);
	if (!sitn->fb_tunnel_dev) {
		err = -ENOMEM;
		goto err_alloc_dev;
	}
	dev_net_set(sitn->fb_tunnel_dev, net);

	ipip6_fb_tunnel_init(sitn->fb_tunnel_dev);

	if ((err = register_netdev(sitn->fb_tunnel_dev)))
		goto err_reg_dev;

	return 0;

err_reg_dev:
	dev_put(sitn->fb_tunnel_dev);
	free_netdev(sitn->fb_tunnel_dev);
err_alloc_dev:
	/* nothing */
err_assign:
	kfree(sitn);
err_alloc:
	return err;
}
Пример #8
0
static int proc_root_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat
)
{
	struct ve_struct *ve = get_exec_env();

	generic_fillattr(dentry->d_inode, stat);
	stat->nlink = glob_proc_root.nlink;
	if (ve_is_super(ve))
		stat->nlink += nr_processes();
#ifdef CONFIG_VE
	else
		/* thread count. not really processes count */
		stat->nlink += ve->pcounter;
	/* the same logic as in the proc_getattr */
	stat->nlink += ve->proc_root->nlink - 2;
#endif
	return 0;
}
Пример #9
0
static struct kobject *ve_kobj_path_create(char *path)
{
	char *e, *p = path;
	struct sysfs_dirent *sd, *parent_sd = get_exec_env()->_sysfs_root;
	struct kobject *k, *pk = NULL;

	if (*p == '/')
		p++;

	while (1) {
		e = strchr(p, '/');
		if (e)
			*e = '\0';
		sd = sysfs_get_dirent(parent_sd, p);
		if (sd == NULL) {
new:			k = kobject_create_and_add(p, pk);
			kobject_put(pk);
			if (!k)
				return ERR_PTR(-ENOMEM);
		} else {
			if (!(sd->s_flags & SYSFS_DIR)) {
Пример #10
0
struct file *get_task_file(pid_t pid, int fd)
{
	int err;
	struct task_struct *tsk;
	struct files_struct *fs;
	struct file *file = NULL;

	err = -ESRCH;
	read_lock(&tasklist_lock);
	tsk = find_task_by_pid_ns(pid, get_exec_env()->ve_ns->pid_ns);
	if (tsk == NULL) {
		read_unlock(&tasklist_lock);
		goto out;
	}

	get_task_struct(tsk);
	read_unlock(&tasklist_lock);

	err = -EINVAL;
	fs = get_files_struct(tsk);
	if (fs == NULL)
		goto out_put;

	rcu_read_lock();
	err = -EBADF;
	file = fcheck_files(fs, fd);
	if (file == NULL)
		goto out_unlock;

	err = 0;
	get_file(file);

out_unlock:
	rcu_read_unlock();
	put_files_struct(fs);
out_put:
	put_task_struct(tsk);
out:
	return err ? ERR_PTR(err) : file;
}
Пример #11
0
static inline struct vfsmount *ve_devmnt(void)
{
	return get_exec_env()->devtmpfs_mnt;
}
Пример #12
0
int rst_socket_in(struct cpt_sock_image *si, loff_t pos, struct sock *sk,
		  struct cpt_context *ctx)
{
	struct inet_sock *inet = inet_sk(sk);
	struct net *net = get_exec_env()->ve_ns->net_ns;
	int err, ret_err = 0;

	lock_sock(sk);

	sk->sk_state = si->cpt_state;

	inet->daddr = si->cpt_daddr;
	inet->dport = si->cpt_dport;
	inet->saddr = si->cpt_saddr;
	inet->rcv_saddr = si->cpt_rcv_saddr;
	inet->sport = si->cpt_sport;
	inet->uc_ttl = si->cpt_uc_ttl;
	inet->tos = si->cpt_tos;
	inet->cmsg_flags = si->cpt_cmsg_flags;
	inet->mc_index = si->cpt_mc_index;
	inet->mc_addr = si->cpt_mc_addr;
	inet->hdrincl = si->cpt_hdrincl;
	inet->mc_ttl = si->cpt_mc_ttl;
	inet->mc_loop = si->cpt_mc_loop;
	inet->pmtudisc = si->cpt_pmtudisc;
	inet->recverr = si->cpt_recverr;
	inet->freebind = si->cpt_freebind;
	inet->id = si->cpt_idcounter;

	inet->cork.flags = si->cpt_cork_flags;
	inet->cork.fragsize = si->cpt_cork_fragsize;
	inet->cork.length = si->cpt_cork_length;
	inet->cork.addr = si->cpt_cork_addr;
	inet->cork.fl.fl4_src = si->cpt_cork_saddr;
	inet->cork.fl.fl4_dst = si->cpt_cork_daddr;
	inet->cork.fl.oif = si->cpt_cork_oif;
	if (inet->cork.fragsize) {
		if (ip_route_output_key(net, (struct rtable **)&inet->cork.dst, &inet->cork.fl)) {
			eprintk_ctx("failed to restore cork route\n");
			inet->cork.fragsize = 0;
		}
	}

	if (sk->sk_type == SOCK_DGRAM && sk->sk_protocol == IPPROTO_UDP) {
		struct udp_sock *up = udp_sk(sk);
		up->pending = si->cpt_udp_pending;
		up->corkflag = si->cpt_udp_corkflag;
		up->encap_type = si->cpt_udp_encap;
		up->len = si->cpt_udp_len;
	}

	if (sk->sk_family == AF_INET6) {
		struct ipv6_pinfo *np = inet6_sk(sk);

		memcpy(&np->saddr, si->cpt_saddr6, 16);
		memcpy(&np->rcv_saddr, si->cpt_rcv_saddr6, 16);
		memcpy(&np->daddr, si->cpt_daddr6, 16);
		np->flow_label = si->cpt_flow_label6;
		np->frag_size = si->cpt_frag_size6;
		np->hop_limit = si->cpt_hop_limit6;
		np->mcast_hops = si->cpt_mcast_hops6;
		np->mcast_oif = si->cpt_mcast_oif6;
		np->rxopt.all = si->cpt_rxopt6;
		np->mc_loop = si->cpt_mc_loop6;
		np->recverr = si->cpt_recverr6;
		np->sndflow = si->cpt_sndflow6;
		np->pmtudisc = si->cpt_pmtudisc6;
		np->ipv6only = si->cpt_ipv6only6;

#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
		if (si->cpt_mapped) {
			extern struct inet_connection_sock_af_ops ipv6_mapped;
			if (sk->sk_type == SOCK_STREAM &&
			    sk->sk_protocol == IPPROTO_TCP) {
				inet_csk(sk)->icsk_af_ops = &ipv6_mapped;
				sk->sk_backlog_rcv = tcp_v4_do_rcv;
			}
		}
#endif
	}

	err = restore_queues(sk, si, pos, ctx);

	if (sk->sk_type == SOCK_STREAM && sk->sk_protocol == IPPROTO_TCP) {
		ret_err = err;
		rst_socket_tcp(si, pos, sk, ctx);
	}

	release_sock(sk);
	return ret_err;
}
Пример #13
0
int rst_restore_ifaddr(struct cpt_context *ctx)
{
	struct net *net = get_exec_env()->ve_netns;
	int err;
	loff_t sec = ctx->sections[CPT_SECT_NET_IFADDR];
	loff_t endsec;
	struct cpt_section_hdr h;
	struct cpt_ifaddr_image di;
	struct net_device *dev;

	if (sec == CPT_NULL)
		return 0;

	err = ctx->pread(&h, sizeof(h), ctx, sec);
	if (err)
		return err;
	if (h.cpt_section != CPT_SECT_NET_IFADDR || h.cpt_hdrlen < sizeof(h))
		return -EINVAL;

	endsec = sec + h.cpt_next;
	sec += h.cpt_hdrlen;
	while (sec < endsec) {
		int cindex = -1;
		int err;
		err = rst_get_object(CPT_OBJ_NET_IFADDR, sec, &di, ctx);
		if (err)
			return err;
		cindex = di.cpt_index;
		rtnl_lock();
		dev = __dev_get_by_index(net, cindex);
		if (dev && di.cpt_family == AF_INET) {
			struct in_device *in_dev;
			struct in_ifaddr *ifa;
			if ((in_dev = __in_dev_get_rtnl(dev)) == NULL)
				in_dev = inetdev_init(dev);
			ifa = inet_alloc_ifa();
			if (ifa) {
				ifa->ifa_local = di.cpt_address[0];
				ifa->ifa_address = di.cpt_peer[0];
				ifa->ifa_broadcast = di.cpt_broadcast[0];
				ifa->ifa_prefixlen = di.cpt_masklen;
				ifa->ifa_mask = inet_make_mask(ifa->ifa_prefixlen);
				ifa->ifa_flags = di.cpt_flags;
				ifa->ifa_scope = di.cpt_scope;
				memcpy(ifa->ifa_label, di.cpt_label, IFNAMSIZ);
				in_dev_hold(in_dev);
				ifa->ifa_dev   = in_dev;
				err = inet_insert_ifa(ifa);
				if (err && err != -EEXIST) {
					rtnl_unlock();
					eprintk_ctx("add ifaddr err %d for %d %s\n", err, di.cpt_index, di.cpt_label);
					return err;
				}
			}
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
		} else if (dev && di.cpt_family == AF_INET6) {
			__u32 prefered_lft;
			__u32 valid_lft;
			struct net *net = get_exec_env()->ve_ns->net_ns;
			prefered_lft = (di.cpt_flags & IFA_F_DEPRECATED) ?
				0 : di.cpt_prefered_lft;
			valid_lft = (di.cpt_flags & IFA_F_PERMANENT) ?
				0xFFFFFFFF : di.cpt_valid_lft;
			err = inet6_addr_add(net, dev->ifindex,
					     (struct in6_addr *)di.cpt_address,
					     di.cpt_masklen, 0,
					     prefered_lft,
					     valid_lft);
			if (err && err != -EEXIST) {
				rtnl_unlock();
				eprintk_ctx("add ifaddr err %d for %d %s\n", err, di.cpt_index, di.cpt_label);
				return err;
			}
#endif
		} else {
			rtnl_unlock();
			eprintk_ctx("unknown ifaddr 2 for %d\n", di.cpt_index);
			return -EINVAL;
		}
		rtnl_unlock();
		sec += di.cpt_next;
	}
	return 0;
}
Пример #14
0
int rst_restore_netdev(struct cpt_context *ctx)
{
	struct net *net = get_exec_env()->ve_netns;
	int err;
	loff_t sec = ctx->sections[CPT_SECT_NET_DEVICE];
	loff_t endsec;
	struct cpt_section_hdr h;
	struct cpt_netdev_image di;
	struct net_device *dev;

	get_exec_env()->disable_net = 1;

	if (sec == CPT_NULL)
		return 0;

	err = ctx->pread(&h, sizeof(h), ctx, sec);
	if (err)
		return err;
	if (h.cpt_section != CPT_SECT_NET_DEVICE || h.cpt_hdrlen < sizeof(h))
		return -EINVAL;

	endsec = sec + h.cpt_next;
	sec += h.cpt_hdrlen;
	while (sec < endsec) {
		loff_t pos;
		struct net_device *dev_new;
		struct netdev_rst *ops;

		err = rst_get_object(CPT_OBJ_NET_DEVICE, sec, &di, ctx);
		if (err)
			return err;

		rtnl_lock();
		pos = sec + di.cpt_hdrlen;
		if (di.cpt_next > sizeof(di)) {
			struct cpt_object_hdr hdr;
			err = ctx->pread(&hdr, sizeof(struct cpt_object_hdr),
					ctx, sec + di.cpt_hdrlen);
			if (err)
				goto out;

			ops = NULL;
			while (1) {
				ops = netdev_find_rst(hdr.cpt_object, ops);
				if (ops == NULL)
					break;

				err = ops->ndo_rst(sec, &di, &rst_ops, ctx);
				if (!err) {
					pos += hdr.cpt_next;
					break;
				} else if (err < 0) {
					eprintk_ctx("netdev %d rst failed %d\n",
							hdr.cpt_object, err);
					goto out;
				}
			}
		}

		dev = __dev_get_by_name(net, di.cpt_name);
		if (dev) {
			if (dev->ifindex != di.cpt_index) {
				dev_new = __dev_get_by_index(net, di.cpt_index);
				if (!dev_new) {
					write_lock_bh(&dev_base_lock);
					hlist_del(&dev->index_hlist);
					if (dev->iflink == dev->ifindex)
						dev->iflink = di.cpt_index;
					dev->ifindex = di.cpt_index;
					hlist_add_head(&dev->index_hlist,
							dev_index_hash(net, dev->ifindex));
					write_unlock_bh(&dev_base_lock);
				} else {
					write_lock_bh(&dev_base_lock);
					hlist_del(&dev->index_hlist);
					hlist_del(&dev_new->index_hlist);
					if (dev_new->iflink == dev_new->ifindex)
						dev_new->iflink = dev->ifindex;
					dev_new->ifindex = dev->ifindex;
					if (dev->iflink == dev->ifindex)
						dev->iflink = di.cpt_index;
					dev->ifindex = di.cpt_index;
					hlist_add_head(&dev->index_hlist,
							dev_index_hash(net, dev->ifindex));
					hlist_add_head(&dev_new->index_hlist,
							dev_index_hash(net, dev_new->ifindex));
					write_unlock_bh(&dev_base_lock);
				}
			}
			if (di.cpt_flags^dev->flags) {
				err = dev_change_flags(dev, di.cpt_flags);
				if (err)
					eprintk_ctx("dev_change_flags err: %d\n", err);
			}
			while (pos < sec + di.cpt_next) {
				struct cpt_object_hdr hdr;
				err = ctx->pread(&hdr, sizeof(struct cpt_object_hdr),
						ctx, pos);
				if (err)
					goto out;
				if (hdr.cpt_object == CPT_OBJ_NET_HWADDR) {
					/* Restore hardware address */
					struct cpt_hwaddr_image hw;
					err = rst_get_object(CPT_OBJ_NET_HWADDR,
							pos, &hw, ctx);
					if (err)
						goto out;
					BUILD_BUG_ON(sizeof(hw.cpt_dev_addr) !=
							MAX_ADDR_LEN);
					memcpy(dev->dev_addr, hw.cpt_dev_addr,
							sizeof(hw.cpt_dev_addr));
				} else if (hdr.cpt_object == CPT_OBJ_NET_STATS) {
					err = rst_restore_netstats(pos, dev, ctx);
					if (err) {
						eprintk_ctx("rst stats %s: %d\n",
								di.cpt_name, err);
						goto out;
					}
				}
				pos += hdr.cpt_next;
			}
		} else {
			eprintk_ctx("unknown interface 2 %s\n", di.cpt_name);
		}
		rtnl_unlock();
		sec += di.cpt_next;
	}
	return 0;
out:
	rtnl_unlock();
	return err;
}
Пример #15
0
static int uts_arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
{
	struct uts_namespace *uts_ns = current->nsproxy->uts_ns;
	struct ve_struct *ve = get_exec_env();
	int i, n1, n2, n3, new_version;
	struct page **new_pages, **p;

	/*
	 * For node or in case we've not changed UTS simply
	 * map preallocated original vDSO.
	 *
	 * In turn if we already allocated one for this UTS
	 * simply reuse it. It improves speed significantly.
	 */
	if (uts_ns == &init_uts_ns)
		goto map_init_uts;
	/*
	 * Dirty lockless hack. Strictly speaking
	 * we need to return @p here if it's non-nil,
	 * but since there only one trasition possible
	 * { =0 ; !=0 } we simply return @uts_ns->vdso.pages
	 */
	p = ACCESS_ONCE(uts_ns->vdso.pages);
	smp_read_barrier_depends();
	if (p)
		goto map_uts;

	if (sscanf(uts_ns->name.release, "%d.%d.%d", &n1, &n2, &n3) == 3) {
		/*
		 * If there were no changes on version simply reuse
		 * preallocated one.
		 */
		new_version = KERNEL_VERSION(n1, n2, n3);
		if (new_version == LINUX_VERSION_CODE)
			goto map_init_uts;
	} else {
		/*
		 * If admin is passed malformed string here
		 * lets warn him once but continue working
		 * not using vDSO virtualization at all. It's
		 * better than walk out with error.
		 */
		pr_warn_once("Wrong release uts name format detected."
			     " Ignoring vDSO virtualization.\n");
		goto map_init_uts;
	}

	mutex_lock(&vdso_mutex);
	if (uts_ns->vdso.pages) {
		mutex_unlock(&vdso_mutex);
		goto map_uts;
	}

	uts_ns->vdso.nr_pages	= init_uts_ns.vdso.nr_pages;
	uts_ns->vdso.size	= init_uts_ns.vdso.size;
	uts_ns->vdso.version_off= init_uts_ns.vdso.version_off;
	new_pages		= kmalloc(sizeof(struct page *) * init_uts_ns.vdso.nr_pages, GFP_KERNEL);
	if (!new_pages) {
		pr_err("Can't allocate vDSO pages array for VE %d\n", ve->veid);
		goto out_unlock;
	}

	for (i = 0; i < uts_ns->vdso.nr_pages; i++) {
		struct page *p = alloc_page(GFP_KERNEL);
		if (!p) {
			pr_err("Can't allocate page for VE %d\n", ve->veid);
			for (; i > 0; i--)
				put_page(new_pages[i - 1]);
			kfree(new_pages);
			goto out_unlock;
		}
		new_pages[i] = p;
		copy_page(page_address(p), page_address(init_uts_ns.vdso.pages[i]));
	}

	uts_ns->vdso.addr = vmap(new_pages, uts_ns->vdso.nr_pages, 0, PAGE_KERNEL);
	if (!uts_ns->vdso.addr) {
		pr_err("Can't map vDSO pages for VE %d\n", ve->veid);
		for (i = 0; i < uts_ns->vdso.nr_pages; i++)
			put_page(new_pages[i]);
		kfree(new_pages);
		goto out_unlock;
	}

	*((int *)(uts_ns->vdso.addr + uts_ns->vdso.version_off)) = new_version;
	smp_wmb();
	uts_ns->vdso.pages = new_pages;
	mutex_unlock(&vdso_mutex);

	pr_debug("vDSO version transition %d -> %d for VE %d\n",
		 LINUX_VERSION_CODE, new_version, ve->veid);

map_uts:
	return setup_additional_pages(bprm, uses_interp, uts_ns->vdso.pages, uts_ns->vdso.size);
map_init_uts:
	return setup_additional_pages(bprm, uses_interp, init_uts_ns.vdso.pages, init_uts_ns.vdso.size);
out_unlock:
	mutex_unlock(&vdso_mutex);
	return -ENOMEM;
}
Пример #16
0
static int sit_rst(loff_t start, struct cpt_netdev_image *di,
		struct rst_ops *ops, struct cpt_context *ctx)
{
	int err = -ENODEV;
	struct cpt_tunnel_image v;
	struct net_device *dev;
	struct ip_tunnel *t;
	loff_t pos;
	int fbdev;
	struct sit_net *sitn;

	sitn = net_generic(get_exec_env()->ve_netns, sit_net_id);
	if (sitn == NULL)
		return -EOPNOTSUPP;

	pos = start + di->cpt_hdrlen;
	err = ops->get_object(CPT_OBJ_NET_IPIP_TUNNEL,
			pos, &v, sizeof(v), ctx);
	if (err)
		return err;

	/* some sanity */
	if (v.cpt_content != CPT_CONTENT_VOID)
		return -EINVAL;

	if (!(v.cpt_tnl_flags & CPT_TUNNEL_SIT))
		return 1;

	if (v.cpt_tnl_flags & CPT_TUNNEL_FBDEV) {
		fbdev = 1;
		err = 0;
		dev = sitn->fb_tunnel_dev;
	} else {
		fbdev = 0;
		err = -ENOMEM;
		dev = alloc_netdev(sizeof(struct ip_tunnel), di->cpt_name,
				ipip6_tunnel_setup);
		if (!dev)
			goto out;
	}

	t = netdev_priv(dev);
	t->parms.i_flags = v.cpt_i_flags;
	t->parms.o_flags = v.cpt_o_flags;
	t->parms.i_key = v.cpt_i_key;
	t->parms.o_key = v.cpt_o_key;

	BUILD_BUG_ON(sizeof(v.cpt_iphdr) != sizeof(t->parms.iph));
	memcpy(&t->parms.iph, &v.cpt_iphdr, sizeof(t->parms.iph));

	if (!fbdev) {
		ipip6_tunnel_init(dev);
		err = register_netdevice(dev);
		if (err) {
			free_netdev(dev);
			goto out;
		}

		dev_hold(dev);
		ipip6_tunnel_link(sitn, t);
	}
out:
	return err;
}
Пример #17
0
int cpt_suspend_network(struct cpt_context *ctx)
{
	get_exec_env()->disable_net = 1;
	synchronize_net();
	return 0;
}
Пример #18
0
int cpt_dump_ifaddr(struct cpt_context * ctx)
{
	struct net *net = get_exec_env()->ve_netns;
	struct net_device *dev;

	cpt_open_section(ctx, CPT_SECT_NET_IFADDR);
	for_each_netdev(net, dev) {
		struct in_device *idev = in_dev_get(dev);
		struct in_ifaddr *ifa;

		if (!idev)
			continue;

		for (ifa = idev->ifa_list; ifa; ifa = ifa->ifa_next) {
			struct cpt_ifaddr_image v;
			cpt_open_object(NULL, ctx);

			v.cpt_next = CPT_NULL;
			v.cpt_object = CPT_OBJ_NET_IFADDR;
			v.cpt_hdrlen = sizeof(v);
			v.cpt_content = CPT_CONTENT_VOID;

			v.cpt_index = dev->ifindex;
			v.cpt_family = AF_INET;
			v.cpt_masklen = ifa->ifa_prefixlen;
			v.cpt_flags = ifa->ifa_flags;
			v.cpt_scope = ifa->ifa_scope;
			memset(&v.cpt_address, 0, sizeof(v.cpt_address));
			memset(&v.cpt_peer, 0, sizeof(v.cpt_peer));
			memset(&v.cpt_broadcast, 0, sizeof(v.cpt_broadcast));
			v.cpt_address[0] = ifa->ifa_local;
			v.cpt_peer[0] = ifa->ifa_address;
			v.cpt_broadcast[0] = ifa->ifa_broadcast;
			memcpy(v.cpt_label, ifa->ifa_label, IFNAMSIZ);
			ctx->write(&v, sizeof(v), ctx);
			cpt_close_object(ctx);
		}
		in_dev_put(idev);
	}
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
	for_each_netdev(net, dev) {
		struct inet6_dev *idev = in6_dev_get(dev);
		struct inet6_ifaddr *ifa;

		if (!idev)
			continue;

		for (ifa = idev->addr_list; ifa; ifa = ifa->if_next) {
			struct cpt_ifaddr_image v;

			if (dev == net->loopback_dev &&
			    ifa->prefix_len == 128 &&
			    ifa->addr.s6_addr32[0] == 0 &&
			    ifa->addr.s6_addr32[1] == 0 &&
			    ifa->addr.s6_addr32[2] == 0 &&
			    ifa->addr.s6_addr32[3] == htonl(1))
				continue;

			cpt_open_object(NULL, ctx);

			v.cpt_next = CPT_NULL;
			v.cpt_object = CPT_OBJ_NET_IFADDR;
			v.cpt_hdrlen = sizeof(v);
			v.cpt_content = CPT_CONTENT_VOID;

			v.cpt_index = dev->ifindex;
			v.cpt_family = AF_INET6;
			v.cpt_masklen = ifa->prefix_len;
			v.cpt_flags = ifa->flags;
			v.cpt_scope = ifa->scope;
			v.cpt_valid_lft = ifa->valid_lft;
			v.cpt_prefered_lft = ifa->prefered_lft;
			memcpy(&v.cpt_address, &ifa->addr, 16);
			memcpy(&v.cpt_peer, &ifa->addr, 16);
			memset(&v.cpt_broadcast, 0, sizeof(v.cpt_broadcast));
			memcpy(v.cpt_label, dev->name, IFNAMSIZ);
			ctx->write(&v, sizeof(v), ctx);
			cpt_close_object(ctx);
		}
		in6_dev_put(idev);
	}
#endif
	cpt_close_section(ctx);
	return 0;
}
Пример #19
0
static int cpt_dump_iptables(struct cpt_context * ctx)
{
	int err = 0;
#ifdef CONFIG_VE_IPTABLES
	int pid;
	int pfd[2];
	struct file *f;
	struct cpt_object_hdr v;
	char buf[16];
	loff_t pos;
	int n;
	int status;
	mm_segment_t oldfs;
	sigset_t ignore, blocked;
	struct args_t args;
	struct ve_struct *oldenv;

	if (!(get_exec_env()->_iptables_modules & VE_IP_IPTABLES_MOD))
		return 0;

	err = sc_pipe(pfd);
	if (err < 0) {
		eprintk_ctx("sc_pipe: %d\n", err);
		return err;
	}
	args.pfd = pfd;
	args.veid = VEID(get_exec_env());
	ignore.sig[0] = CPT_SIG_IGNORE_MASK;
	sigprocmask(SIG_BLOCK, &ignore, &blocked);
	oldenv = set_exec_env(get_ve0());
	err = pid = local_kernel_thread(dumpfn, (void*)&args,
			SIGCHLD | CLONE_VFORK, 0);
	set_exec_env(oldenv);
	if (err < 0) {
		eprintk_ctx("local_kernel_thread: %d\n", err);
		goto out;
	}

	f = fget(pfd[0]);
	sc_close(pfd[1]);
	sc_close(pfd[0]);

	cpt_open_section(ctx, CPT_SECT_NET_IPTABLES);

	cpt_open_object(NULL, ctx);
	v.cpt_next = CPT_NULL;
	v.cpt_object = CPT_OBJ_NAME;
	v.cpt_hdrlen = sizeof(v);
	v.cpt_content = CPT_CONTENT_NAME;

	ctx->write(&v, sizeof(v), ctx);

	pos = ctx->file->f_pos;
	do {
		oldfs = get_fs(); set_fs(KERNEL_DS);
		n = f->f_op->read(f, buf, sizeof(buf), &f->f_pos);
		set_fs(oldfs);
		if (n > 0)
			ctx->write(buf, n, ctx);
	} while (n > 0);

	if (n < 0)
		eprintk_ctx("read: %d\n", n);

	fput(f);

	oldfs = get_fs(); set_fs(KERNEL_DS);
	if ((err = sc_waitx(pid, 0, &status)) < 0)
		eprintk_ctx("wait4: %d\n", err);
	else if ((status & 0x7f) == 0) {
		err = (status & 0xff00) >> 8;
		if (err != 0) {
			eprintk_ctx("iptables-save exited with %d\n", err);
			err = -EINVAL;
		}
	} else {
Пример #20
0
/**
 * kthread_create_ve - create a kthread.
 * @threadfn: the function to run until signal_pending(current).
 * @data: data ptr for @threadfn.
 * @namefmt: printf-style name for the thread.
 *
 * Description: This helper function creates and names a kernel
 * thread.  The thread will be stopped: use wake_up_process() to start
 * it.  See also kthread_run(), kthread_create_on_cpu().
 *
 * When woken, the thread will run @threadfn() with @data as its
 * argument. @threadfn() can either call do_exit() directly if it is a
 * standalone thread for which noone will call kthread_stop(), or
 * return when 'kthread_should_stop()' is true (which means
 * kthread_stop() has been called).  The return value should be zero
 * or a negative error number; it will be passed to kthread_stop().
 *
 * Returns a task_struct or ERR_PTR(-ENOMEM).
 */
struct task_struct *kthread_create_ve(struct ve_struct *ve,
				   int (*threadfn)(void *data),
				   void *data,
				   const char namefmt[],
				   ...)
{
	struct kthread_create_info create;
	struct ve_struct *old_ve;

	old_ve = set_exec_env(ve);

	create.threadfn = threadfn;
	create.data = data;
	init_completion(&create.done);

	spin_lock(&kthread_create_lock);
	list_add_tail(&create.list, &kthread_create_list);
	spin_unlock(&kthread_create_lock);

	wake_up_process(kthreadd_task);
	wait_for_completion(&create.done);

	if (!IS_ERR(create.result)) {
		struct sched_param param = { .sched_priority = 0 };
		va_list args;

		va_start(args, namefmt);
		vsnprintf(create.result->comm, sizeof(create.result->comm),
			  namefmt, args);
		va_end(args);
		/*
		 * root may have changed our (kthreadd's) priority or CPU mask.
		 * The kernel thread should not inherit these properties.
		 */
		sched_setscheduler_nocheck(create.result, SCHED_NORMAL, &param);
		set_cpus_allowed_ptr(create.result, cpu_all_mask);
	}

	set_exec_env(old_ve);

	return create.result;
}
EXPORT_SYMBOL(kthread_create_ve);

/**
 * kthread_stop - stop a thread created by kthread_create().
 * @k: thread created by kthread_create().
 *
 * Sets kthread_should_stop() for @k to return true, wakes it, and
 * waits for it to exit. This can also be called after kthread_create()
 * instead of calling wake_up_process(): the thread will exit without
 * calling threadfn().
 *
 * If threadfn() may call do_exit() itself, the caller must ensure
 * task_struct can't go away.
 *
 * Returns the result of threadfn(), or %-EINTR if wake_up_process()
 * was never called.
 */
int kthread_stop(struct task_struct *k)
{
	struct kthread *kthread;
	int ret;

	trace_sched_kthread_stop(k);
	get_task_struct(k);

	kthread = to_kthread(k);
	barrier(); /* it might have exited */
	if (k->vfork_done != NULL) {
		kthread->should_stop = 1;
		wake_up_process(k);
		wait_for_completion(&kthread->exited);
	}
	ret = k->exit_code;

	put_task_struct(k);
	trace_sched_kthread_stop_ret(ret);

	return ret;
}
EXPORT_SYMBOL(kthread_stop);

int kthreadd(void *data)
{
	struct task_struct *tsk = current;
	struct kthreadd_create_info *kcreate;
	struct kthread self;
	int rc;

	self.should_stop = 0;

	kcreate = (struct kthreadd_create_info *) data;

	if (kcreate) {
		daemonize("kthreadd/%d", get_exec_env()->veid);
		kcreate->result = current;
		set_fs(KERNEL_DS);
		init_completion(&self.exited);
		current->vfork_done = &self.exited;
	} else
		set_task_comm(tsk, "kthreadd");

	/* Setup a clean context for our children to inherit. */
	ignore_signals(tsk);
	set_cpus_allowed_ptr(tsk, cpu_all_mask);
	set_mems_allowed(node_states[N_HIGH_MEMORY]);

	current->flags |= PF_NOFREEZE | PF_FREEZER_NOSIG;

	if (kcreate)
		complete(&kcreate->done);

	for (;;) {
		set_current_state(TASK_INTERRUPTIBLE);
		if (list_empty(&kthread_create_list)) {
			if (self.should_stop)
				break;
			else
				schedule();
		}
		__set_current_state(TASK_RUNNING);

		spin_lock(&kthread_create_lock);
		while (!list_empty(&kthread_create_list)) {
			struct kthread_create_info *create;

			create = list_entry(kthread_create_list.next,
					    struct kthread_create_info, list);
			list_del_init(&create->list);
			spin_unlock(&kthread_create_lock);

			create_kthread(create);

			spin_lock(&kthread_create_lock);
		}
		spin_unlock(&kthread_create_lock);
	}

	do {
		clear_thread_flag(TIF_SIGPENDING);
		rc = sys_wait4(-1, NULL, __WALL, NULL);
	} while (rc != -ECHILD);

	do_exit(0);
}

int kthreadd_create()
{
	struct kthreadd_create_info create;
	int ret;
	struct ve_struct *ve = get_exec_env();

	BUG_ON(ve->_kthreadd_task);

	INIT_LIST_HEAD(&ve->_kthread_create_list);
	init_completion(&create.done);
	ret = kernel_thread(kthreadd, (void *) &create, CLONE_FS);
	if (ret < 0) {
		return ret;
	}
	wait_for_completion(&create.done);
	ve->_kthreadd_task = create.result;
	return 0;
}
EXPORT_SYMBOL(kthreadd_create);

void kthreadd_stop(struct ve_struct *ve)
{
	struct kthread *kthread;
	int ret;
	struct task_struct *k;

	if (!ve->_kthreadd_task)
		return;

	k = ve->_kthreadd_task;
	trace_sched_kthread_stop(k);
	get_task_struct(k);

	BUG_ON(!k->vfork_done);

	kthread = container_of(k->vfork_done, struct kthread, exited);
	kthread->should_stop = 1;
	wake_up_process(k);
	wait_for_completion(&kthread->exited);
	ret = k->exit_code;

	put_task_struct(k);
	trace_sched_kthread_stop_ret(ret);
}
EXPORT_SYMBOL(kthreadd_stop);
Пример #21
0
static int show_cpuinfo(struct seq_file *m, void *v)
{
	struct cpuinfo_x86 *c = v;
	unsigned int cpu;
	int is_super = ve_is_super(get_exec_env());
	int i;

	cpu = c->cpu_index;
	seq_printf(m, "processor\t: %u\n"
		   "vendor_id\t: %s\n"
		   "cpu family\t: %d\n"
		   "model\t\t: %u\n"
		   "model name\t: %s\n",
		   cpu,
		   c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown",
		   c->x86,
		   c->x86_model,
		   c->x86_model_id[0] ? c->x86_model_id : "unknown");

	if (c->x86_mask || c->cpuid_level >= 0)
		seq_printf(m, "stepping\t: %d\n", c->x86_mask);
	else
		seq_printf(m, "stepping\t: unknown\n");
	if (c->microcode)
		seq_printf(m, "microcode\t: 0x%x\n", c->microcode);

	if (cpu_has(c, X86_FEATURE_TSC)) {
		unsigned int freq = cpufreq_quick_get(cpu);

		if (!freq)
			freq = cpu_khz;
		freq = sched_cpulimit_scale_cpufreq(freq);
		seq_printf(m, "cpu MHz\t\t: %u.%03u\n",
			   freq / 1000, (freq % 1000));
	}

	/* Cache size */
	if (c->x86_cache_size >= 0)
		seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size);

	show_cpuinfo_core(m, c, cpu);
	show_cpuinfo_misc(m, c);

	seq_printf(m, "flags\t\t:");
	for (i = 0; i < 32*NCAPINTS; i++)
		if (x86_cap_flags[i] != NULL &&
				((is_super && cpu_has(c, i)) ||
				 (!is_super && test_bit(i, (unsigned long *)
							&per_cpu(cpu_flags, cpu)))))
			seq_printf(m, " %s", x86_cap_flags[i]);

	seq_printf(m, "\nbogomips\t: %lu.%02lu\n",
		   c->loops_per_jiffy/(500000/HZ),
		   (c->loops_per_jiffy/(5000/HZ)) % 100);

#ifdef CONFIG_X86_64
	if (c->x86_tlbsize > 0)
		seq_printf(m, "TLB size\t: %d 4K pages\n", c->x86_tlbsize);
#endif
	seq_printf(m, "clflush size\t: %u\n", c->x86_clflush_size);
	seq_printf(m, "cache_alignment\t: %d\n", c->x86_cache_alignment);
	seq_printf(m, "address sizes\t: %u bits physical, %u bits virtual\n",
		   c->x86_phys_bits, c->x86_virt_bits);

	seq_printf(m, "power management:");
	for (i = 0; i < 32; i++) {
		if (c->x86_power & (1 << i)) {
			if (i < ARRAY_SIZE(x86_power_flags) &&
			    x86_power_flags[i])
				seq_printf(m, "%s%s",
					   x86_power_flags[i][0] ? " " : "",
					   x86_power_flags[i]);
			else
				seq_printf(m, " [%d]", i);
		}
	}

	seq_printf(m, "\n\n");

	return 0;
}