#include <sys/types.h>
#include "config.h"
+#include "log.h"
#include "namespace.h"
#include "network.h"
#include "parse.h"
fprintf(stderr, "{nicname} is the name to use inside the container\n");
if (fail)
- exit(EXIT_FAILURE);
+ _exit(EXIT_FAILURE);
- exit(EXIT_SUCCESS);
+ _exit(EXIT_SUCCESS);
}
static int open_and_lock(char *path)
fd = open(path, O_RDWR | O_CREAT, S_IWUSR | S_IRUSR);
if (fd < 0) {
- usernic_error("Failed to open \"%s\": %s\n", path,
- strerror(errno));
+ CMD_SYSERROR("Failed to open \"%s\"\n", path);
return -1;
}
ret = fcntl(fd, F_SETLKW, &lk);
if (ret < 0) {
- usernic_error("Failed to lock \"%s\": %s\n", path,
- strerror(errno));
+ CMD_SYSERROR("Failed to lock \"%s\"\n", path);
close(fd);
return -1;
}
if (ret == 0)
usernic_error("%s", "Could not find matched password record\n");
- usernic_error("Failed to get username: %s(%u)\n", strerror(errno), getuid());
+ CMD_SYSERROR("Failed to get username: %u\n", getuid());
free(buf);
return NULL;
}
ngroups = getgroups(0, NULL);
if (ngroups < 0) {
- usernic_error("Failed to get number of groups the user "
- "belongs to: %s\n", strerror(errno));
+ CMD_SYSERROR("Failed to get number of groups the user belongs to\n");
return NULL;
- }
- if (ngroups == 0)
+ } else if (ngroups == 0) {
return NULL;
+ }
group_ids = malloc(sizeof(gid_t) * ngroups);
if (!group_ids) {
- usernic_error("Failed to allocate memory while getting groups "
- "the user belongs to: %s\n",
- strerror(errno));
+ CMD_SYSERROR("Failed to allocate memory while getting groups the user belongs to\n");
return NULL;
}
ret = getgroups(ngroups, group_ids);
if (ret < 0) {
free(group_ids);
- usernic_error("Failed to get process groups: %s\n",
- strerror(errno));
+ CMD_SYSERROR("Failed to get process groups\n");
return NULL;
}
groupnames = malloc(sizeof(char *) * (ngroups + 1));
if (!groupnames) {
free(group_ids);
- usernic_error("Failed to allocate memory while getting group "
- "names: %s\n",
- strerror(errno));
+ CMD_SYSERROR("Failed to allocate memory while getting group names\n");
return NULL;
}
if (!buf) {
free(group_ids);
free_groupnames(groupnames);
- usernic_error("Failed to allocate memory while getting group "
- "names: %s\n",
- strerror(errno));
+ CMD_SYSERROR("Failed to allocate memory while getting group names\n");
return NULL;
}
if (ret == 0)
usernic_error("%s", "Could not find matched group record\n");
- usernic_error("Failed to get group name: %s(%u)\n",
- strerror(errno), group_ids[i]);
+ CMD_SYSERROR("Failed to get group name: %u\n", group_ids[i]);
free(buf);
free(group_ids);
free_groupnames(groupnames);
groupnames[i] = strdup(grent.gr_name);
if (!groupnames[i]) {
- usernic_error("Failed to copy group name \"%s\"",
- grent.gr_name);
+ usernic_error("Failed to copy group name \"%s\"", grent.gr_name);
free(buf);
free(group_ids);
free_groupnames(groupnames);
return true;
groupnames++;
}
+
return false;
}
al = malloc(sizeof(struct alloted_s));
if (!al) {
- usernic_error("Failed to allocate memory: %s\n",
- strerror(errno));
+ CMD_SYSERROR("Failed to allocate memory\n");
return NULL;
}
char name[100], type[100], br[100];
char **groups;
FILE *fin;
-
int count = 0;
size_t len = 0;
char *line = NULL;
fin = fopen(LXC_USERNIC_CONF, "r");
if (!fin) {
- usernic_error("Failed to open \"%s\": %s\n", LXC_USERNIC_CONF,
- strerror(errno));
+ CMD_SYSERROR("Failed to open \"%s\"\n", LXC_USERNIC_CONF);
return -1;
}
count = 0;
break;
}
+
count += n;
}
{
while ((s < e) && *s && (*s != '\n'))
s++;
+
return s;
}
{
while ((s < e) && *s && !isblank(*s) && (*s != '\n'))
s++;
+
return s;
}
ret = lxc_veth_create(veth1, veth2);
if (ret < 0) {
- usernic_error("Failed to create %s-%s : %s.\n", veth1, veth2,
- strerror(-ret));
+ errno = -ret;
+ CMD_SYSERROR("Failed to create %s-%s\n", veth1, veth2);
return -1;
}
* mac address of a container.
*/
ret = setup_private_host_hw_addr(veth1);
- if (ret < 0)
- usernic_error("Failed to change mac address of host interface "
- "%s : %s\n", veth1, strerror(-ret));
+ if (ret < 0) {
+ errno = -ret;
+ CMD_SYSERROR("Failed to change mac address of host interface %s\n", veth1);
+ }
return netdev_set_flag(veth1, IFF_UP);
}
idx = if_nametoindex(name);
if (idx < 0)
return -1;
+
return netdev_get_mtu(idx);
}
usernic_error("%s\n", "Could not create nic name");
return -1;
}
+
/* create the nics */
ret = instantiate_veth(veth1buf, veth2buf);
if (ret < 0) {
ret = lxc_netdev_set_mtu(veth1buf, mtu);
if (ret < 0) {
usernic_error("Failed to set mtu to %d on %s\n",
- mtu, veth1buf);
+ mtu, veth1buf);
goto out_del;
}
ret = lxc_netdev_set_mtu(veth2buf, mtu);
if (ret < 0) {
usernic_error("Failed to set mtu to %d on %s\n",
- mtu, veth2buf);
+ mtu, veth2buf);
goto out_del;
}
}
ret = lxc_netdev_move_by_name(veth2buf, pid, NULL);
if (ret < 0) {
usernic_error("Error moving %s to network namespace of %d\n",
- veth2buf, pid);
+ veth2buf, pid);
goto out_del;
}
ret = fstat(fd, &sb);
if (ret < 0) {
- usernic_error("Failed to fstat: %s\n", strerror(errno));
+ CMD_SYSERROR("Failed to fstat\n");
return false;
}
buf = lxc_strmmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (buf == MAP_FAILED) {
- usernic_error("Failed to establish shared memory mapping: %s\n",
- strerror(errno));
+ CMD_SYSERROR("Failed to establish shared memory mapping\n");
return false;
}
}
buf_start = buf;
+
for (i = 0; i < n; i++) {
if (!entry_lines[i].keep)
continue;
*buf_start = '\n';
buf_start++;
}
+
free(entry_lines);
ret = ftruncate(fd, buf_start - buf);
lxc_strmunmap(buf, sb.st_size);
if (ret < 0)
- usernic_error("Failed to set new file size: %s\n",
- strerror(errno));
+ CMD_SYSERROR("Failed to set new file size\n");
return true;
}
&owner, &(bool){true}, &(bool){true}))) {
if (owner)
count++;
+
buf = get_eol(buf, buf_end) + 1;
if (buf >= buf_end)
break;
ret = fstat(fd, &sb);
if (ret < 0) {
- usernic_error("Failed to fstat: %s\n", strerror(errno));
+ CMD_SYSERROR("Failed to fstat\n");
return NULL;
}
buf = lxc_strmmap(NULL, sb.st_size, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
if (buf == MAP_FAILED) {
- usernic_error("Failed to establish shared memory "
- "mapping: %s\n", strerror(errno));
+ CMD_SYSERROR("Failed to establish shared memory mapping\n");
return NULL;
}
owner = NULL;
+
for (n = names; n != NULL; n = n->next) {
count = count_entries(buf, sb.st_size, n->name, intype, br);
if (count >= n->allowed)
newline = malloc(slen + 1);
if (!newline) {
free(newline);
- usernic_error("Failed allocate memory: %s\n", strerror(errno));
+ CMD_SYSERROR("Failed allocate memory\n");
return NULL;
}
if (ret < 0 || (size_t)ret >= (slen + 1)) {
if (lxc_netdev_delete_by_name(nicname) != 0)
usernic_error("Error unlinking %s\n", nicname);
+
free(newline);
return NULL;
}
*/
ret = ftruncate(fd, sb.st_size + slen);
if (ret < 0)
- usernic_error("Failed to truncate file: %s\n", strerror(errno));
+ CMD_SYSERROR("Failed to truncate file\n");
buf = lxc_strmmap(NULL, sb.st_size + slen, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
if (buf == MAP_FAILED) {
- usernic_error("Failed to establish shared memory mapping: %s\n",
- strerror(errno));
+ CMD_SYSERROR("Failed to establish shared memory mapping\n");
+
if (lxc_netdev_delete_by_name(nicname) != 0)
usernic_error("Error unlinking %s\n", nicname);
+
free(newline);
return NULL;
}
again:
while (*p && *p != '/')
p++;
+
if (!*p)
return true;
ret = mkdir(fnam, 0755);
if (ret < 0 && errno != EEXIST) {
- usernic_error("Failed to create %s: %s\n", fnam,
- strerror(errno));
+ CMD_SYSERROR("Failed to create %s\n", fnam);
*p = '/';
return false;
}
+
*(p++) = '/';
goto again;
int fd = -1, ifindex = -1, ofd = -1;
pid_self = lxc_raw_getpid();
+
ofd = lxc_preserve_ns(pid_self, "net");
if (ofd < 0) {
usernic_error("Failed opening network namespace path for %d", pid_self);
ret = getresuid(&ruid, &euid, &suid);
if (ret < 0) {
- usernic_error("Failed to retrieve real, effective, and saved "
- "user IDs: %s\n",
- strerror(errno));
+ CMD_SYSERROR("Failed to retrieve real, effective, and saved user IDs\n");
goto do_partial_cleanup;
}
close(fd);
fd = -1;
if (ret < 0) {
- usernic_error("Failed to setns() to the network namespace of "
- "the container with PID %d: %s\n",
- pid, strerror(errno));
+ CMD_SYSERROR("Failed to setns() to the network namespace of "
+ "the container with PID %d\n", pid);
goto do_partial_cleanup;
}
ret = setresuid(ruid, ruid, 0);
if (ret < 0) {
- usernic_error("Failed to drop privilege by setting effective "
- "user id and real user id to %d, and saved user "
- "ID to 0: %s\n",
- ruid, strerror(errno));
+ CMD_SYSERROR("Failed to drop privilege by setting effective "
+ "user id and real user id to %d, and saved user "
+ "ID to 0\n", ruid);
/* It's ok to jump to do_full_cleanup here since setresuid()
* will succeed when trying to set real, effective, and saved to
* values they currently have.
/* Check if old interface exists. */
ifindex = if_nametoindex(oldname);
if (!ifindex) {
- usernic_error("Failed to get netdev index: %s\n", strerror(errno));
+ CMD_SYSERROR("Failed to get netdev index\n");
goto do_full_cleanup;
}
name = NULL;
if (ret < 0) {
usernic_error("Error %d renaming netdev %s to %s in container\n",
- ret, oldname, newname ? newname : "eth%d");
+ ret, oldname, newname ? newname : "eth%d");
goto do_full_cleanup;
}
/* Retrieve new name for interface. */
if (!if_indextoname(ifindex, ifname)) {
- usernic_error("Failed to get new netdev name: %s\n", strerror(errno));
+ CMD_SYSERROR("Failed to get new netdev name\n");
goto do_full_cleanup;
}
do_full_cleanup:
ret = setresuid(ruid, euid, suid);
if (ret < 0) {
- usernic_error("Failed to restore privilege by setting "
- "effective user id to %d, real user id to %d, "
- "and saved user ID to %d: %s\n", ruid, euid, suid,
- strerror(errno));
+ CMD_SYSERROR("Failed to restore privilege by setting "
+ "effective user id to %d, real user id to %d, "
+ "and saved user ID to %d\n", ruid, euid, suid);
string_ret = NULL;
}
ret = setns(ofd, CLONE_NEWNET);
if (ret < 0) {
- usernic_error("Failed to setns() to original network namespace "
- "of PID %d: %s\n", ofd, strerror(errno));
+ CMD_SYSERROR("Failed to setns() to original network namespace "
+ "of PID %d\n", ofd);
string_ret = NULL;
}
ret = getresuid(&ruid, &euid, &suid);
if (ret < 0) {
- usernic_error("Failed to retrieve real, effective, and saved "
- "user IDs: %s\n",
- strerror(errno));
+ CMD_SYSERROR("Failed to retrieve real, effective, and saved user IDs\n");
return false;
}
ret = setresuid(ruid, ruid, euid);
if (ret < 0) {
- usernic_error("Failed to drop privilege by setting effective "
- "user id and real user id to %d, and saved user "
- "ID to %d: %s\n",
- ruid, euid, strerror(errno));
+ CMD_SYSERROR("Failed to drop privilege by setting effective "
+ "user id and real user id to %d, and saved user "
+ "ID to %d\n", ruid, euid);
return false;
}
may_access = true;
if (ret < 0) {
may_access = false;
- usernic_error("Uid %d may not access %s: %s\n", (int)ruid, s, strerror(errno));
+ CMD_SYSERROR("Uid %d may not access %s\n", (int)ruid, s);
}
ret = setresuid(ruid, euid, suid);
if (ret < 0) {
- usernic_error("Failed to restore user id to %d, real user id "
- "to %d, and saved user ID to %d: %s\n",
- ruid, euid, suid, strerror(errno));
+ CMD_SYSERROR("Failed to restore user id to %d, real user id "
+ "to %d, and saved user ID to %d\n", ruid, euid, suid);
may_access = false;
}
int ofd = -1;
pid_self = lxc_raw_getpid();
+
ofd = lxc_preserve_ns(pid_self, "net");
if (ofd < 0) {
usernic_error("Failed opening network namespace path for %d", pid_self);
ret = getresuid(&ruid, &euid, &suid);
if (ret < 0) {
- usernic_error("Failed to retrieve real, effective, and saved "
- "user IDs: %s\n",
- strerror(errno));
+ CMD_SYSERROR("Failed to retrieve real, effective, and saved user IDs\n");
goto do_partial_cleanup;
}
ret = setns(netns_fd, CLONE_NEWNET);
if (ret < 0) {
- usernic_error("Failed to setns() to network namespace %s\n",
- strerror(errno));
+ CMD_SYSERROR("Failed to setns() to network namespace\n");
goto do_partial_cleanup;
}
ret = setresuid(ruid, ruid, 0);
if (ret < 0) {
- usernic_error("Failed to drop privilege by setting effective "
- "user id and real user id to %d, and saved user "
- "ID to 0: %s\n",
- ruid, strerror(errno));
+ CMD_SYSERROR("Failed to drop privilege by setting effective "
+ "user id and real user id to %d, and saved user "
+ "ID to 0\n", ruid);
/* It's ok to jump to do_full_cleanup here since setresuid()
* will succeed when trying to set real, effective, and saved to
* values they currently have.
do_full_cleanup:
ret = setresuid(ruid, euid, suid);
if (ret < 0) {
- usernic_error("Failed to restore privilege by setting "
- "effective user id to %d, real user id to %d, "
- "and saved user ID to %d: %s\n", ruid, euid, suid,
- strerror(errno));
-
+ CMD_SYSERROR("Failed to restore privilege by setting "
+ "effective user id to %d, real user id to %d, "
+ "and saved user ID to %d\n", ruid, euid, suid);
bret = false;
}
ret = setns(ofd, CLONE_NEWNET);
if (ret < 0) {
- usernic_error("Failed to setns() to original network namespace "
- "of PID %d: %s\n", ofd, strerror(errno));
-
+ CMD_SYSERROR("Failed to setns() to original network namespace "
+ "of PID %d\n", ofd);
bret = false;
}
do_partial_cleanup:
-
close(ofd);
return bret;
}
if (argc < 7 || argc > 8) {
usage(argv[0], true);
- exit(EXIT_FAILURE);
+ _exit(EXIT_FAILURE);
}
memset(&args, 0, sizeof(struct user_nic_args));
+
args.cmd = argv[1];
args.lxc_path = argv[2];
args.lxc_name = argv[3];
request = LXC_USERNIC_DELETE;
} else {
usage(argv[0], true);
- exit(EXIT_FAILURE);
+ _exit(EXIT_FAILURE);
}
/* Set a sane env, because we are setuid-root. */
ret = clearenv();
if (ret) {
usernic_error("%s", "Failed to clear environment\n");
- exit(EXIT_FAILURE);
+ _exit(EXIT_FAILURE);
}
ret = setenv("PATH", "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 1);
if (ret < 0) {
usernic_error("%s", "Failed to set PATH, exiting\n");
- exit(EXIT_FAILURE);
+ _exit(EXIT_FAILURE);
}
me = get_username();
if (!me) {
usernic_error("%s", "Failed to get username\n");
- exit(EXIT_FAILURE);
+ _exit(EXIT_FAILURE);
}
if (request == LXC_USERNIC_CREATE) {
ret = lxc_safe_int(args.pid, &pid);
if (ret < 0) {
usernic_error("Could not read pid: %s\n", args.pid);
- exit(EXIT_FAILURE);
+ _exit(EXIT_FAILURE);
}
} else if (request == LXC_USERNIC_DELETE) {
char opath[LXC_PROC_PID_FD_LEN];
netns_fd = open(args.pid, O_PATH | O_CLOEXEC);
if (netns_fd < 0) {
usernic_error("Failed to open \"%s\"\n", args.pid);
- exit(EXIT_FAILURE);
+ _exit(EXIT_FAILURE);
}
if (!fhas_fs_type(netns_fd, NSFS_MAGIC)) {
usernic_error("Path \"%s\" does not refer to a network namespace path\n", args.pid);
close(netns_fd);
- exit(EXIT_FAILURE);
+ _exit(EXIT_FAILURE);
}
ret = snprintf(opath, sizeof(opath), "/proc/self/fd/%d", netns_fd);
if (ret < 0 || (size_t)ret >= sizeof(opath)) {
close(netns_fd);
- exit(EXIT_FAILURE);
+ _exit(EXIT_FAILURE);
}
/* Now get an fd that we can use in setns() calls. */
ret = open(opath, O_RDONLY | O_CLOEXEC);
if (ret < 0) {
- usernic_error("Failed to open \"%s\": %s\n", args.pid, strerror(errno));
+ CMD_SYSERROR("Failed to open \"%s\"\n", args.pid);
close(netns_fd);
- exit(EXIT_FAILURE);
+ _exit(EXIT_FAILURE);
}
+
close(netns_fd);
netns_fd = ret;
}
if (!create_db_dir(LXC_USERNIC_DB)) {
usernic_error("%s", "Failed to create directory for db file\n");
+
if (netns_fd >= 0)
close(netns_fd);
- exit(EXIT_FAILURE);
+
+ _exit(EXIT_FAILURE);
}
fd = open_and_lock(LXC_USERNIC_DB);
if (fd < 0) {
usernic_error("Failed to lock %s\n", LXC_USERNIC_DB);
+
if (netns_fd >= 0)
close(netns_fd);
- exit(EXIT_FAILURE);
+
+ _exit(EXIT_FAILURE);
}
if (request == LXC_USERNIC_CREATE) {
if (!may_access_netns(pid)) {
usernic_error("User %s may not modify netns for pid %d\n", me, pid);
- exit(EXIT_FAILURE);
+ _exit(EXIT_FAILURE);
}
} else if (request == LXC_USERNIC_DELETE) {
bool has_priv;
+
has_priv = is_privileged_over_netns(netns_fd);
close(netns_fd);
if (!has_priv) {
usernic_error("%s", "Process is not privileged over "
- "network namespace\n");
- exit(EXIT_FAILURE);
+ "network namespace\n");
+ _exit(EXIT_FAILURE);
}
}
if (!is_ovs_bridge(args.link)) {
usernic_error("%s", "Deletion of non ovs type network "
- "devices not implemented\n");
+ "devices not implemented\n");
close(fd);
free_alloted(&alloted);
- exit(EXIT_FAILURE);
+ _exit(EXIT_FAILURE);
}
/* Check whether the network device we are supposed to delete
if (!found_nicname) {
usernic_error("Caller is not allowed to delete network "
- "device \"%s\"\n", args.veth_name);
- exit(EXIT_FAILURE);
+ "device \"%s\"\n", args.veth_name);
+ _exit(EXIT_FAILURE);
}
ret = lxc_ovs_delete_port(args.link, args.veth_name);
if (ret < 0) {
usernic_error("Failed to remove port \"%s\" from "
- "openvswitch bridge \"%s\"",
- args.veth_name, args.link);
- exit(EXIT_FAILURE);
+ "openvswitch bridge \"%s\"",
+ args.veth_name, args.link);
+ _exit(EXIT_FAILURE);
}
- exit(EXIT_SUCCESS);
+ _exit(EXIT_SUCCESS);
}
+
if (n > 0)
nicname = get_nic_if_avail(fd, alloted, pid, args.type,
args.link, n, &cnic);
close(fd);
free_alloted(&alloted);
+
if (!nicname) {
usernic_error("%s", "Quota reached\n");
- exit(EXIT_FAILURE);
+ _exit(EXIT_FAILURE);
}
/* Now rename the link. */
&container_veth_ifidx);
if (!newname) {
usernic_error("%s", "Failed to rename the link\n");
+
ret = lxc_netdev_delete_by_name(cnic);
if (ret < 0)
usernic_error("Failed to delete \"%s\"\n", cnic);
+
free(nicname);
- exit(EXIT_FAILURE);
+ _exit(EXIT_FAILURE);
}
host_veth_ifidx = if_nametoindex(nicname);
if (!host_veth_ifidx) {
free(newname);
free(nicname);
- usernic_error("Failed to get netdev index: %s\n", strerror(errno));
- exit(EXIT_FAILURE);
+ CMD_SYSERROR("Failed to get netdev index\n");
+ _exit(EXIT_FAILURE);
}
/* Write names of veth pairs and their ifindeces to stout:
host_veth_ifidx);
free(newname);
free(nicname);
- exit(EXIT_SUCCESS);
+
+ fflush(stdout);
+ _exit(EXIT_SUCCESS);
}