[lxc-devel] [PATCH 1/9] lxc_user_nic: add a check to make sure caller owns target netns

Stéphane Graber stgraber at ubuntu.com
Tue Nov 19 21:49:56 UTC 2013


On Tue, Nov 19, 2013 at 04:17:44PM +0000, Serge Hallyn wrote:
> From: Serge Hallyn <serge.hallyn at ubuntu.com>
> 
> Temporarily set our euid back to the calling ruid, so that the
> access(2) check can succeed based on the euid being the userns
> creator.
> 
> Also switch from atoi to strtol
> 
> Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>

Acked-by: Stéphane Graber <stgraber at ubuntu.com>

> ---
>  src/lxc/lxc_user_nic.c | 64 +++++++++++++++++++++++++++++++++++++++++++++-----
>  1 file changed, 58 insertions(+), 6 deletions(-)
> 
> diff --git a/src/lxc/lxc_user_nic.c b/src/lxc/lxc_user_nic.c
> index e4f59fa..c8513ba 100644
> --- a/src/lxc/lxc_user_nic.c
> +++ b/src/lxc/lxc_user_nic.c
> @@ -540,7 +540,7 @@ int lxc_netdev_delete_by_name(const char *name)
>  
>  #endif
>  
> -bool create_nic(char *nic, char *br, char *pidstr, char **cnic)
> +bool create_nic(char *nic, char *br, int pid, char **cnic)
>  {
>  #if ISTEST
>  	char path[200];
> @@ -556,7 +556,6 @@ bool create_nic(char *nic, char *br, char *pidstr, char **cnic)
>  	veth1buf = alloca(IFNAMSIZ);
>  	veth2buf = alloca(IFNAMSIZ);
>  	int ret;
> -	int pid = atoi(pidstr);
>  
>  	ret = snprintf(veth1buf, IFNAMSIZ, "%s", nic);
>  	if (ret < 0 || ret >= IFNAMSIZ) {
> @@ -596,7 +595,7 @@ out_del:
>   * *dest will container the name (lxcuser-%d) which is attached
>   * on the host to the lxc bridge
>   */
> -void get_new_nicname(char **dest, char *br, char *pid, char **cnic)
> +void get_new_nicname(char **dest, char *br, int pid, char **cnic)
>  {
>  	int i = 0;
>  	// TODO - speed this up.  For large installations we won't
> @@ -679,7 +678,7 @@ int count_entries(char *buf, off_t len, char *me, char *t, char *br)
>   * The dbfile has lines of the format:
>   * user type bridge nicname
>   */
> -bool get_nic_if_avail(int fd, char *me, char *pid, char *intype, char *br, int allowed, char **nicname, char **cnic)
> +bool get_nic_if_avail(int fd, char *me, int pid, char *intype, char *br, int allowed, char **nicname, char **cnic)
>  {
>  	off_t len, slen;
>  	struct stat sb;
> @@ -857,6 +856,47 @@ out_err:
>  	return -1;
>  }
>  
> +/*
> + * If the caller (real uid, not effective uid) may read the
> + * /proc/pid/net/ns, then it is either the caller's netns or one
> + * which it created.
> + */
> +static bool may_access_netns(int pid)
> +{
> +	int ret;
> +	char s[200];
> +	uid_t ruid, suid, euid;
> +	bool may_access = false;
> +
> +	ret = getresuid(&ruid, &euid, &suid);
> +	if (ret) {
> +		fprintf(stderr, "Failed to get my uids: %s\n", strerror(errno));
> +		return false;
> +	}
> +	ret = setresuid(ruid, ruid, euid);
> +	if (ret) {
> +		fprintf(stderr, "Failed to set temp uids to (%d,%d,%d): %s\n",
> +				(int)ruid, (int)ruid, (int)euid, strerror(errno));
> +		return false;
> +	}
> +	ret = snprintf(s, 200, "/proc/%d/ns/net", pid);
> +	if (ret < 0 || ret >= 200)  // can't happen
> +		return false;
> +	ret = access(s, R_OK);
> +	if (ret) {
> +		fprintf(stderr, "Uid %d may not access %s: %s\n",
> +				(int)ruid, s, strerror(errno));
> +	}
> +	may_access = ret == 0;
> +	ret = setresuid(ruid, euid, suid);
> +	if (ret) {
> +		fprintf(stderr, "Failed to restore uids to (%d,%d,%d): %s\n",
> +				(int)ruid, (int)euid, (int)suid, strerror(errno));
> +		may_access = false;
> +	}
> +	return may_access;
> +}
> +
>  int main(int argc, char *argv[])
>  {
>  	int n, fd;
> @@ -879,6 +919,13 @@ int main(int argc, char *argv[])
>  	else
>  		vethname = "eth0";
>  
> +	errno = 0;
> +	pid = (int) strtol(argv[1], NULL, 10);
> +	if (errno) {
> +		fprintf(stderr, "Could not read pid: %s\n", argv[1]);
> +		exit(1);
> +	}
> +
>  	if (!create_db_dir(DB_FILE)) {
>  		fprintf(stderr, "Failed to create directory for db file\n");
>  		exit(1);
> @@ -889,16 +936,21 @@ int main(int argc, char *argv[])
>  		exit(1);
>  	}
>  
> +	if (!may_access_netns(pid)) {
> +		fprintf(stderr, "User %s may not modify netns for pid %d\n",
> +				me, pid);
> +		exit(1);
> +	}
> +
>  	n = get_alloted(me, argv[2], argv[3]);
>  	if (n > 0)
> -		gotone = get_nic_if_avail(fd, me, argv[1], argv[2], argv[3], n, &nicname, &cnic);
> +		gotone = get_nic_if_avail(fd, me, pid, argv[2], argv[3], n, &nicname, &cnic);
>  	close(fd);
>  	if (!gotone) {
>  		fprintf(stderr, "Quota reached\n");
>  		exit(1);
>  	}
>  
> -	pid = atoi(argv[1]);
>  	// Now rename the link
>  	if (rename_in_ns(pid, cnic, vethname) < 0) {
>  		fprintf(stderr, "Failed to rename the link\n");
> -- 
> 1.8.3.2
> 
> 
> ------------------------------------------------------------------------------
> Shape the Mobile Experience: Free Subscription
> Software experts and developers: Be at the forefront of tech innovation.
> Intel(R) Software Adrenaline delivers strategic insight and game-changing 
> conversations that shape the rapidly evolving mobile landscape. Sign up now. 
> http://pubads.g.doubleclick.net/gampad/clk?id=63431311&iu=/4140/ostg.clktrk
> _______________________________________________
> Lxc-devel mailing list
> Lxc-devel at lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/lxc-devel

-- 
Stéphane Graber
Ubuntu developer
http://www.ubuntu.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20131119/fb6bdfb5/attachment.pgp>


More information about the lxc-devel mailing list