示例#1
0
文件: utils.c 项目: justinHume/lxc
int lxc_read_from_file(const char *filename, void* buf, size_t count)
{
	int fd = -1, saved_errno;
	ssize_t ret;

	process_lock();
	fd = open(filename, O_RDONLY | O_CLOEXEC);
	process_unlock();
	if (fd < 0)
		return -1;

	if (!buf || !count) {
		char buf2[100];
		size_t count2 = 0;
		while ((ret = read(fd, buf2, 100)) > 0)
			count2 += ret;
		if (ret >= 0)
			ret = count2;
	} else {
		memset(buf, 0, count);
		ret = read(fd, buf, count);
	}

	if (ret < 0)
		ERROR("read %s: %s", filename, strerror(errno));

	saved_errno = errno;
	process_lock();
	close(fd);
	process_unlock();
	errno = saved_errno;
	return ret;
}
示例#2
0
文件: parse.c 项目: LuciferoO/lxc
int lxc_file_for_each_line(const char *file, lxc_file_cb callback, void *data)
{
	FILE *f;
	int err = 0;
	char *line = NULL;
	size_t len = 0;

	process_lock();
	f = fopen(file, "r");
	process_unlock();
	if (!f) {
		SYSERROR("failed to open %s", file);
		return -1;
	}

	while (getline(&line, &len, f) != -1) {
		err = callback(line, data);
		if (err) {
			ERROR("Failed to parse config: %s", line);
			break;
		}
	}

	if (line)
		free(line);
	process_lock();
	fclose(f);
	process_unlock();
	return err;
}
示例#3
0
static void lxc_monitor_fifo_send(struct lxc_msg *msg, const char *lxcpath)
{
	int fd,ret;
	char fifo_path[PATH_MAX];

	BUILD_BUG_ON(sizeof(*msg) > PIPE_BUF); /* write not guaranteed atomic */

	ret = lxc_monitor_fifo_name(lxcpath, fifo_path, sizeof(fifo_path), 0);
	if (ret < 0)
		return;

	process_lock();
	fd = open(fifo_path, O_WRONLY);
	process_unlock();
	if (fd < 0) {
		/* it is normal for this open to fail when there is no monitor
		 * running, so we don't log it
		 */
		return;
	}

	ret = write(fd, msg, sizeof(*msg));
	if (ret != sizeof(*msg)) {
		process_lock();
		close(fd);
		process_unlock();
		SYSERROR("failed to write monitor fifo %s", fifo_path);
		return;
	}

	process_lock();
	close(fd);
	process_unlock();
}
示例#4
0
文件: utils.c 项目: justinHume/lxc
int lxc_write_to_file(const char *filename, const void* buf, size_t count, bool add_newline)
{
	int fd, saved_errno;
	ssize_t ret;

	process_lock();
	fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, 0666);
	process_unlock();
	if (fd < 0)
		return -1;
	ret = lxc_write_nointr(fd, buf, count);
	if (ret < 0)
		goto out_error;
	if ((size_t)ret != count)
		goto out_error;
	if (add_newline) {
		ret = lxc_write_nointr(fd, "\n", 1);
		if (ret != 1)
			goto out_error;
	}
	process_lock();
	close(fd);
	process_unlock();
	return 0;

out_error:
	saved_errno = errno;
	process_lock();
	close(fd);
	process_unlock();
	errno = saved_errno;
	return -1;
}
示例#5
0
文件: apparmor.c 项目: angushe/lxc
static char *apparmor_process_label_get(pid_t pid)
{
	char path[100], *space;
	int ret;
	char *buf = NULL;
	int sz = 0;
	FILE *f;

	ret = snprintf(path, 100, "/proc/%d/attr/current", pid);
	if (ret < 0 || ret >= 100) {
		ERROR("path name too long");
		return NULL;
	}
again:
	process_lock();
	f = fopen(path, "r");
	process_unlock();
	if (!f) {
		SYSERROR("opening %s\n", path);
		if (buf)
			free(buf);
		return NULL;
	}
	sz += 1024;
	buf = realloc(buf, sz);
	if (!buf) {
		ERROR("out of memory");
		process_lock();
		fclose(f);
		process_unlock();
		return NULL;
	}
	memset(buf, 0, sz);
	ret = fread(buf, 1, sz - 1, f);
	process_lock();
	fclose(f);
	process_unlock();
	if (ret < 0) {
		ERROR("reading %s\n", path);
		free(buf);
		return NULL;
	}
	if (ret >= sz)
		goto again;
	space = index(buf, '\n');
	if (space)
		*space = '\0';
	space = index(buf, ' ');
	if (space)
		*space = '\0';
	return buf;
}
示例#6
0
文件: lxclock.c 项目: ArikaChen/lxc
int lxclock(struct lxc_lock *l, int timeout)
{
	int ret = -1, saved_errno = errno;
	struct flock lk;

	switch(l->type) {
	case LXC_LOCK_ANON_SEM:
		if (!timeout) {
			ret = sem_wait(l->u.sem);
			if (ret == -1)
				saved_errno = errno;
		} else {
			struct timespec ts;
			if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
				ret = -2;
				goto out;
			}
			ts.tv_sec += timeout;
			ret = sem_timedwait(l->u.sem, &ts);
			if (ret == -1)
				saved_errno = errno;
		}
		break;
	case LXC_LOCK_FLOCK:
		ret = -2;
		if (timeout) {
			ERROR("Error: timeout not supported with flock");
			ret = -2;
			goto out;
		}
		if (!l->u.f.fname) {
			ERROR("Error: filename not set for flock");
			ret = -2;
			goto out;
		}
		process_lock();
		if (l->u.f.fd == -1) {
			l->u.f.fd = open(l->u.f.fname, O_RDWR|O_CREAT,
					S_IWUSR | S_IRUSR);
			if (l->u.f.fd == -1) {
				process_unlock();
				ERROR("Error opening %s", l->u.f.fname);
				goto out;
			}
		}
		lk.l_type = F_WRLCK;
		lk.l_whence = SEEK_SET;
		lk.l_start = 0;
		lk.l_len = 0;
		ret = fcntl(l->u.f.fd, F_SETLKW, &lk);
		process_unlock();
		if (ret == -1)
			saved_errno = errno;
		break;
	}

out:
	errno = saved_errno;
	return ret;
}
示例#7
0
/* routines used by monitor publishers (containers) */
int lxc_monitor_fifo_name(const char *lxcpath, char *fifo_path, size_t fifo_path_sz,
			  int do_mkdirp)
{
	int ret;
	const char *rundir;

	rundir = get_rundir();
	if (do_mkdirp) {
		ret = snprintf(fifo_path, fifo_path_sz, "%s/lxc/%s", rundir, lxcpath);
		if (ret < 0 || ret >= fifo_path_sz) {
			ERROR("rundir/lxcpath (%s/%s) too long for monitor fifo", rundir, lxcpath);
			return -1;
		}
		process_lock();
		ret = mkdir_p(fifo_path, 0755);
		process_unlock();
		if (ret < 0) {
			ERROR("unable to create monitor fifo dir %s", fifo_path);
			return ret;
		}
	}
	ret = snprintf(fifo_path, fifo_path_sz, "%s/lxc/%s/monitor-fifo", rundir, lxcpath);
	if (ret < 0 || ret >= fifo_path_sz) {
		ERROR("rundir/lxcpath (%s/%s) too long for monitor fifo", rundir, lxcpath);
		return -1;
	}
	return 0;
}
示例#8
0
int process_login (void)
{
	char pword[MAX_USER_NAME];
	char user[MAX_USER_PASSWORD];
	int  u1count = 0;

	memset (user, 0, sizeof(user));

	memset (pword, 0, sizeof(pword));

retry:
	if (u1count == MAX_TRY) {
		process_lock ();
		u1count = 0;
		goto login;
	}
	else {
login:
		write_string ("\nlogin:"******"\nPassword:"******"\nIncorrect Login, Please try again");
			u1count++;
			goto retry;
		}
		set_current_user_name (user);
	}
	write_string ("\n");
	return 0;
}
示例#9
0
文件: lxclock.c 项目: ArikaChen/lxc
int lxcunlock(struct lxc_lock *l)
{
	int ret = 0, saved_errno = errno;
	struct flock lk;

	switch(l->type) {
	case LXC_LOCK_ANON_SEM:
		if (!l->u.sem)
			ret = -2;
		else {
			ret = sem_post(l->u.sem);
			saved_errno = errno;
		}
		break;
	case LXC_LOCK_FLOCK:
		process_lock();
		if (l->u.f.fd != -1) {
			lk.l_type = F_UNLCK;
			lk.l_whence = SEEK_SET;
			lk.l_start = 0;
			lk.l_len = 0;
			ret = fcntl(l->u.f.fd, F_SETLK, &lk);
			if (ret < 0)
				saved_errno = errno;
			close(l->u.f.fd);
			l->u.f.fd = -1;
		} else
			ret = -2;
		process_unlock();
		break;
	}

	errno = saved_errno;
	return ret;
}
示例#10
0
文件: lxclock.c 项目: ArikaChen/lxc
/*
 * lxc_putlock() is only called when a container_new() fails,
 * or during container_put(), which is already guaranteed to
 * only be done by one task.
 * So the only exclusion we need to provide here is for regular
 * thread safety (i.e. file descriptor table changes).
 */
void lxc_putlock(struct lxc_lock *l)
{
	if (!l)
		return;
	switch(l->type) {
	case LXC_LOCK_ANON_SEM:
		if (l->u.sem) {
			sem_close(l->u.sem);
			free(l->u.sem);
			l->u.sem = NULL;
		}
		break;
	case LXC_LOCK_FLOCK:
		process_lock();
		if (l->u.f.fd != -1) {
			close(l->u.f.fd);
			l->u.f.fd = -1;
		}
		process_unlock();
		if (l->u.f.fname) {
			free(l->u.f.fname);
			l->u.f.fname = NULL;
		}
		break;
	}
	free(l);
}
示例#11
0
文件: utils.c 项目: justinHume/lxc
static inline int lock_fclose(FILE *f)
{
	int ret;
	process_lock();
	ret = fclose(f);
	process_unlock();
	return ret;
}
示例#12
0
/* routines used by monitor subscribers (lxc-monitor) */
int lxc_monitor_close(int fd)
{
	int ret;

	process_lock();
	ret = close(fd);
	process_unlock();
	return ret;
}
示例#13
0
文件: seccomp.c 项目: ArikaChen/lxc
int lxc_read_seccomp_config(struct lxc_conf *conf)
{
	FILE *f;
	int ret;

	if (!conf->seccomp)
		return 0;

#if HAVE_SCMP_FILTER_CTX
	/* XXX for debug, pass in SCMP_ACT_TRAP */
	conf->seccomp_ctx = seccomp_init(SCMP_ACT_ERRNO(31));
	ret = !conf->seccomp_ctx;
#else
	ret = seccomp_init(SCMP_ACT_ERRNO(31)) < 0;
#endif
	if (ret) {
		ERROR("failed initializing seccomp");
		return -1;
	}

	/* turn of no-new-privs.  We don't want it in lxc, and it breaks
	 * with apparmor */
	if (seccomp_attr_set(
#if HAVE_SCMP_FILTER_CTX
			conf->seccomp_ctx,
#endif
			SCMP_FLTATR_CTL_NNP, 0)) {
		ERROR("failed to turn off n-new-privs\n");
		return -1;
	}

	process_lock();
	f = fopen(conf->seccomp, "r");
	process_unlock();
	if (!f) {
		SYSERROR("failed to open seccomp policy file %s\n", conf->seccomp);
		return -1;
	}
	ret = parse_config(f, conf);
	process_lock();
	fclose(f);
	process_unlock();
	return ret;
}
示例#14
0
int lxc_monitor_open(const char *lxcpath)
{
	struct sockaddr_un addr;
	int fd,ret;
	int retry,backoff_ms[] = {10, 50, 100};
	size_t len;

	if (lxc_monitor_sock_name(lxcpath, &addr) < 0)
		return -1;

	process_lock();
	fd = socket(PF_UNIX, SOCK_STREAM, 0);
	process_unlock();
	if (fd < 0) {
		ERROR("socket : %s", strerror(errno));
		return -1;
	}

	len = strlen(&addr.sun_path[1]) + 1;
	if (len >= sizeof(addr.sun_path) - 1) {
		ret = -1;
		errno = ENAMETOOLONG;
		goto err1;
	}

	for (retry = 0; retry < sizeof(backoff_ms)/sizeof(backoff_ms[0]); retry++) {
		ret = connect(fd, (struct sockaddr *)&addr, offsetof(struct sockaddr_un, sun_path) + len);
		if (ret == 0 || errno != ECONNREFUSED)
			break;
		ERROR("connect : backing off %d", backoff_ms[retry]);
		usleep(backoff_ms[retry] * 1000);
	}

	if (ret < 0) {
		ERROR("connect : %s", strerror(errno));
		goto err1;
	}
	return fd;
err1:
	process_lock();
	close(fd);
	process_unlock();
	return ret;
}
示例#15
0
文件: lxcutmp.c 项目: ArikaChen/lxc
int lxc_utmp_add_timer(struct lxc_epoll_descr *descr,
		       lxc_mainloop_callback_t callback, void *data)
{
	int fd, result;
	struct itimerspec timeout;
	struct lxc_utmp *utmp_data = (struct lxc_utmp *)data;

	process_lock();
	fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
	process_unlock();
	if (fd < 0) {
		SYSERROR("failed to create timer");
		return -1;
	}

	DEBUG("Setting up utmp shutdown timer");

	/* set a one second timeout. Repeated. */
	timeout.it_value.tv_sec = 1;
	timeout.it_value.tv_nsec = 0;

	timeout.it_interval.tv_sec = 1;
	timeout.it_interval.tv_nsec = 0;

	result = timerfd_settime(fd, 0, &timeout, NULL);

	if (result < 0) {
		SYSERROR("timerfd_settime:");
		return -1;
	}

	if (lxc_mainloop_add_handler(descr, fd, callback, utmp_data)) {
		SYSERROR("failed to add utmp timer to mainloop");
		process_lock();
		close(fd);
		process_unlock();
		return -1;
	}

	utmp_data->timer_fd = fd;

	return 0;
}
示例#16
0
文件: bdev.c 项目: klim-iv/lxc
/*
 * return block size of dev->src
 */
static int blk_getsize(struct bdev *bdev, unsigned long *size)
{
	int fd, ret;
	char *path = bdev->src;

	if (strcmp(bdev->type, "loop") == 0)
		path = bdev->src + 5;

	process_lock();
	fd = open(path, O_RDONLY);
	process_unlock();
	if (fd < 0)
		return -1;
	ret = ioctl(fd, BLKGETSIZE64, size);
	process_lock();
	close(fd);
	process_unlock();
	return ret;
}
示例#17
0
文件: state.c 项目: ArikaChen/lxc
static lxc_state_t freezer_state(const char *name, const char *lxcpath)
{
	char *cgabspath = NULL;
	char freezer[MAXPATHLEN];
	char status[MAXPATHLEN];
	FILE *file;
	int ret;

	cgabspath = lxc_cgroup_get_hierarchy_abs_path("freezer", name, lxcpath);
	if (!cgabspath)
		return -1;

	ret = snprintf(freezer, MAXPATHLEN, "%s/freezer.state", cgabspath);
	if (ret < 0 || ret >= MAXPATHLEN)
		goto out;

	process_lock();
	file = fopen(freezer, "r");
	process_unlock();
	if (!file) {
		ret = -1;
		goto out;
	}

	ret = fscanf(file, "%s", status);
	process_lock();
	fclose(file);
	process_unlock();

	if (ret == EOF) {
		SYSERROR("failed to read %s", freezer);
		ret = -1;
		goto out;
	}

	ret = lxc_str2state(status);

out:
	free(cgabspath);
	return ret;
}
示例#18
0
文件: utils.c 项目: justinHume/lxc
int sha1sum_file(char *fnam, unsigned char *digest)
{
	char *buf;
	int ret;
	FILE *f;
	long flen;

	if (!fnam)
		return -1;
	process_lock();
	f = fopen_cloexec(fnam, "r");
	process_unlock();
	if (f < 0) {
		SYSERROR("Error opening template");
		return -1;
	}
	if (fseek(f, 0, SEEK_END) < 0) {
		SYSERROR("Error seeking to end of template");
		lock_fclose(f);
		return -1;
	}
	if ((flen = ftell(f)) < 0) {
		SYSERROR("Error telling size of template");
		lock_fclose(f);
		return -1;
	}
	if (fseek(f, 0, SEEK_SET) < 0) {
		SYSERROR("Error seeking to start of template");
		lock_fclose(f);
		return -1;
	}
	if ((buf = malloc(flen+1)) == NULL) {
		SYSERROR("Out of memory");
		lock_fclose(f);
		return -1;
	}
	if (fread(buf, 1, flen, f) != flen) {
		SYSERROR("Failure reading template");
		free(buf);
		lock_fclose(f);
		return -1;
	}
	if (lock_fclose(f) < 0) {
		SYSERROR("Failre closing template");
		free(buf);
		return -1;
	}
	buf[flen] = '\0';
	ret = gnutls_hash_fast(GNUTLS_DIG_SHA1, buf, flen, (void *)digest);
	free(buf);
	return ret;
}
示例#19
0
文件: caps.c 项目: ArikaChen/lxc
static int _real_caps_last_cap(void)
{
	int fd;
	int result = -1;

	/* try to get the maximum capability over the kernel
	* interface introduced in v3.2 */
	process_lock();
	fd = open("/proc/sys/kernel/cap_last_cap", O_RDONLY);
	process_unlock();
	if (fd >= 0) {
		char buf[32];
		char *ptr;
		int n;

		if ((n = read(fd, buf, 31)) >= 0) {
			buf[n] = '\0';
			result = strtol(buf, &ptr, 10);
			if (!ptr || (*ptr != '\0' && *ptr != '\n') ||
			    result == LONG_MIN || result == LONG_MAX)
				result = -1;
		}

		process_lock();
		close(fd);
		process_unlock();
	}

	/* try to get it manually by trying to get the status of
	* each capability indiviually from the kernel */
	if (result < 0) {
		int cap = 0;
		while (prctl(PR_CAPBSET_READ, cap) >= 0) cap++;
		result = cap - 1;
	}

	return result;
}
示例#20
0
文件: apparmor.c 项目: angushe/lxc
/* aa_getcon is not working right now.  Use our hand-rolled version below */
static int apparmor_enabled(void)
{
	struct stat statbuf;
	FILE *fin;
	char e;
	int ret;

	ret = stat(AA_MOUNT_RESTR, &statbuf);
	if (ret != 0)
		return 0;
	process_lock();
	fin = fopen(AA_ENABLED_FILE, "r");
	process_unlock();
	if (!fin)
		return 0;
	ret = fscanf(fin, "%c", &e);
	process_lock();
	fclose(fin);
	process_unlock();
	if (ret == 1 && e == 'Y')
		return 1;
	return 0;
}
示例#21
0
文件: blocking.c 项目: hajuuk/R7000
static BOOL blocking_lock_record_process(blocking_lock_record *blr)
{
	switch(blr->com_type) {
		case SMBlock:
			return process_lock(blr);
		case SMBlockread:
			return process_lockread(blr);
		case SMBlockingX:
			return process_lockingX(blr);
		default:
			DEBUG(0,("blocking_lock_record_process: PANIC - unknown type on blocking lock queue - exiting.!\n"));
			exit_server("PANIC - unknown type on blocking lock queue");
	}
	return False; /* Keep compiler happy. */
}
示例#22
0
文件: lxclock.c 项目: ArikaChen/lxc
static char *lxclock_name(const char *p, const char *n)
{
	int ret;
	int len;
	char *dest;
	const char *rundir;

	/* lockfile will be:
	 * "/run" + "/lock/lxc/$lxcpath/$lxcname + '\0' if root
	 * or
	 * $XDG_RUNTIME_DIR + "/lock/lxc/$lxcpath/$lxcname + '\0' if non-root
	 */

	/* length of "/lock/lxc/" + $lxcpath + "/" + $lxcname + '\0' */
	len = strlen("/lock/lxc/") + strlen(n) + strlen(p) + 2;
	rundir = get_rundir();
	len += strlen(rundir);

	if ((dest = malloc(len)) == NULL)
		return NULL;

	ret = snprintf(dest, len, "%s/lock/lxc/%s", rundir, p);
	if (ret < 0 || ret >= len) {
		free(dest);
		return NULL;
	}
	process_lock();
	ret = mkdir_p(dest, 0755);
	process_unlock();
	if (ret < 0) {
		free(dest);
		return NULL;
	}

	ret = snprintf(dest, len, "%s/lock/lxc/%s/%s", rundir, p, n);
	if (ret < 0 || ret >= len) {
		free(dest);
		return NULL;
	}
	return dest;
}
示例#23
0
文件: lxcutmp.c 项目: ArikaChen/lxc
int lxc_utmp_del_timer(struct lxc_epoll_descr *descr,
		       struct lxc_utmp *utmp_data)
{
	int result;

	DEBUG("Clearing utmp shutdown timer");

	result = lxc_mainloop_del_handler(descr, utmp_data->timer_fd);
	if (result < 0)
		SYSERROR("failed to del utmp timer from mainloop");

	/* shutdown timer_fd */
	process_lock();
	close(utmp_data->timer_fd);
	process_unlock();
	utmp_data->timer_fd = -1;

	if (result < 0)
		return -1;
	else
		return 0;
}
示例#24
0
/**
 * \brief Control request event handler
 *
 * This implementation handles the control requests for the GuiderPort device
 */
void	EVENT_USB_Device_ControlRequest() {
	if (is_control()) {
		if (is_incoming()) {
			switch (USB_ControlRequest.bRequest) {
			case FOCUSER_RESET:
				process_reset();
				break;
			case FOCUSER_SET:
				process_set();
				break;
			case FOCUSER_LOCK:
				process_lock();
				break;
			case FOCUSER_STOP:
				process_stop();
				break;
			case FOCUSER_SERIAL:
				process_serial();
				break;
			}
		}
		if (is_outgoing()) {
			switch (USB_ControlRequest.bRequest) {
			case FOCUSER_GET:
				process_get();
				break;
			case FOCUSER_RCVR:
				process_rcvr();
				break;
			case FOCUSER_SAVED:
				process_saved();
				break;
			}
		}
	}
}
示例#25
0
文件: utils.c 项目: justinHume/lxc
static int _recursive_rmdir_onedev(char *dirname, dev_t pdev)
{
	struct dirent dirent, *direntp;
	DIR *dir;
	int ret, failed=0;
	char pathname[MAXPATHLEN];

	process_lock();
	dir = opendir(dirname);
	process_unlock();
	if (!dir) {
		ERROR("%s: failed to open %s", __func__, dirname);
		return 0;
	}

	while (!readdir_r(dir, &dirent, &direntp)) {
		struct stat mystat;
		int rc;

		if (!direntp)
			break;

		if (!strcmp(direntp->d_name, ".") ||
		    !strcmp(direntp->d_name, ".."))
			continue;

		rc = snprintf(pathname, MAXPATHLEN, "%s/%s", dirname, direntp->d_name);
		if (rc < 0 || rc >= MAXPATHLEN) {
			ERROR("pathname too long");
			failed=1;
			continue;
		}
		ret = lstat(pathname, &mystat);
		if (ret) {
			ERROR("%s: failed to stat %s", __func__, pathname);
			failed=1;
			continue;
		}
		if (mystat.st_dev != pdev)
			continue;
		if (S_ISDIR(mystat.st_mode)) {
			if (!_recursive_rmdir_onedev(pathname, pdev))
				failed=1;
		} else {
			if (unlink(pathname) < 0) {
				ERROR("%s: failed to delete %s", __func__, pathname);
				failed=1;
			}
		}
	}

	if (rmdir(dirname) < 0) {
		ERROR("%s: failed to delete %s", __func__, dirname);
		failed=1;
	}

	process_lock();
	ret = closedir(dir);
	process_unlock();
	if (ret) {
		ERROR("%s: failed to close directory %s", __func__, dirname);
		failed=1;
	}

	return !failed;
}
示例#26
0
文件: bdev.c 项目: klim-iv/lxc
/*
 * Given a bdev (presumably blockdev-based), detect the fstype
 * by trying mounting (in a private mntns) it.
 * @bdev: bdev to investigate
 * @type: preallocated char* in which to write the fstype
 * @len: length of passed in char*
 * Returns length of fstype, of -1 on error
 */
static int detect_fs(struct bdev *bdev, char *type, int len)
{
	int  p[2], ret;
	size_t linelen;
	pid_t pid;
	FILE *f;
	char *sp1, *sp2, *sp3, *line = NULL;
	char *srcdev;

	if (!bdev || !bdev->src || !bdev->dest)
		return -1;

	srcdev = bdev->src;
	if (strcmp(bdev->type, "loop") == 0)
		srcdev = bdev->src + 5;

	process_lock();
	ret = pipe(p);
	process_unlock();
	if (ret < 0)
		return -1;
	if ((pid = fork()) < 0)
		return -1;
	if (pid > 0) {
		int status;
		process_lock();
		close(p[1]);
		process_unlock();
		memset(type, 0, len);
		ret = read(p[0], type, len-1);
		process_lock();
		close(p[0]);
		process_unlock();
		if (ret < 0) {
			SYSERROR("error reading from pipe");
			wait(&status);
			return -1;
		} else if (ret == 0) {
			ERROR("child exited early - fstype not found");
			wait(&status);
			return -1;
		}
		wait(&status);
		type[len-1] = '\0';
		INFO("detected fstype %s for %s", type, srcdev);
		return ret;
	}

	process_unlock(); // we're no longer sharing
	if (unshare(CLONE_NEWNS) < 0)
		exit(1);

	ret = mount_unknow_fs(srcdev, bdev->dest, 0);
	if (ret < 0) {
		ERROR("failed mounting %s onto %s to detect fstype", srcdev, bdev->dest);
		exit(1);
	}
	// if symlink, get the real dev name
	char devpath[MAXPATHLEN];
	char *l = linkderef(srcdev, devpath);
	if (!l)
		exit(1);
	f = fopen("/proc/self/mounts", "r");
	if (!f)
		exit(1);
	while (getline(&line, &linelen, f) != -1) {
		sp1 = index(line, ' ');
		if (!sp1)
			exit(1);
		*sp1 = '\0';
		if (strcmp(line, l))
			continue;
		sp2 = index(sp1+1, ' ');
		if (!sp2)
			exit(1);
		*sp2 = '\0';
		sp3 = index(sp2+1, ' ');
		if (!sp3)
			exit(1);
		*sp3 = '\0';
		sp2++;
		if (write(p[1], sp2, strlen(sp2)) != strlen(sp2))
			exit(1);
		exit(0);
	}
	exit(1);
}
示例#27
0
文件: utils.c 项目: justinHume/lxc
const char *lxc_global_config_value(const char *option_name)
{
	static const char *options[][2] = {
		{ "lvm_vg",          DEFAULT_VG      },
		{ "lvm_thin_pool",   DEFAULT_THIN_POOL },
		{ "zfsroot",         DEFAULT_ZFSROOT },
		{ "lxcpath",         LXCPATH         },
		{ "cgroup.pattern",  DEFAULT_CGROUP_PATTERN },
		{ "cgroup.use",      NULL            },
		{ NULL, NULL },
	};
	/* Protected by a mutex to eliminate conflicting load and store operations */ 
	static const char *values[sizeof(options) / sizeof(options[0])] = { 0 };
	const char *(*ptr)[2];
	const char *value;
	size_t i;
	char buf[1024], *p, *p2;
	FILE *fin = NULL;

	for (i = 0, ptr = options; (*ptr)[0]; ptr++, i++) {
		if (!strcmp(option_name, (*ptr)[0]))
			break;
	}
	if (!(*ptr)[0]) {
		errno = EINVAL;
		return NULL;
	}

	static_lock();
	if (values[i]) {
		value = values[i];
		static_unlock();
		return value;
	}
	static_unlock();

	process_lock();
	fin = fopen_cloexec(LXC_GLOBAL_CONF, "r");
	process_unlock();
	if (fin) {
		while (fgets(buf, 1024, fin)) {
			if (buf[0] == '#')
				continue;
			p = strstr(buf, option_name);
			if (!p)
				continue;
			/* see if there was just white space in front
			 * of the option name
			 */
			for (p2 = buf; p2 < p; p2++) {
				if (*p2 != ' ' && *p2 != '\t')
					break;
			}
			if (p2 < p)
				continue;
			p = strchr(p, '=');
			if (!p)
				continue;
			/* see if there was just white space after
			 * the option name
			 */
			for (p2 += strlen(option_name); p2 < p; p2++) {
				if (*p2 != ' ' && *p2 != '\t')
					break;
			}
			if (p2 < p)
				continue;
			p++;
			while (*p && (*p == ' ' || *p == '\t')) p++;
			if (!*p)
				continue;
			static_lock();
			values[i] = copy_global_config_value(p);
			static_unlock();
			goto out;
		}
	}
	/* could not find value, use default */
	static_lock();
	values[i] = (*ptr)[1];
	/* special case: if default value is NULL,
	 * and there is no config, don't view that
	 * as an error... */
	if (!values[i])
		errno = 0;
	static_unlock();

out:
	process_lock();
	if (fin)
		fclose(fin);
	process_unlock();
	static_lock();
	value = values[i];
	static_unlock();
	return value;
}
示例#28
0
文件: attach.c 项目: ArikaChen/lxc
int lxc_attach_to_ns(pid_t pid, int which)
{
	char path[MAXPATHLEN];
	/* according to <http://article.gmane.org/gmane.linux.kernel.containers.lxc.devel/1429>,
	 * the file for user namepsaces in /proc/$pid/ns will be called
	 * 'user' once the kernel supports it
	 */
	static char *ns[] = { "mnt", "pid", "uts", "ipc", "user", "net" };
	static int flags[] = {
		CLONE_NEWNS, CLONE_NEWPID, CLONE_NEWUTS, CLONE_NEWIPC,
		CLONE_NEWUSER, CLONE_NEWNET
	};
	static const int size = sizeof(ns) / sizeof(char *);
	int fd[size];
	int i, j, saved_errno;


	snprintf(path, MAXPATHLEN, "/proc/%d/ns", pid);
	if (access(path, X_OK)) {
		ERROR("Does this kernel version support 'attach' ?");
		return -1;
	}

	for (i = 0; i < size; i++) {
		/* ignore if we are not supposed to attach to that
		 * namespace
		 */
		if (which != -1 && !(which & flags[i])) {
			fd[i] = -1;
			continue;
		}

		snprintf(path, MAXPATHLEN, "/proc/%d/ns/%s", pid, ns[i]);
		process_lock();
		fd[i] = open(path, O_RDONLY | O_CLOEXEC);
		process_unlock();
		if (fd[i] < 0) {
			saved_errno = errno;

			/* close all already opened file descriptors before
			 * we return an error, so we don't leak them
			 */
			process_lock();
			for (j = 0; j < i; j++)
				close(fd[j]);
			process_unlock();

			errno = saved_errno;
			SYSERROR("failed to open '%s'", path);
			return -1;
		}
	}

	for (i = 0; i < size; i++) {
		if (fd[i] >= 0 && setns(fd[i], 0) != 0) {
			saved_errno = errno;

			for (j = i; j < size; j++)
				close(fd[j]);

			errno = saved_errno;
			SYSERROR("failed to set namespace '%s'", ns[i]);
			return -1;
		}

		process_lock();
		close(fd[i]);
		process_unlock();
	}

	return 0;
}
示例#29
0
文件: attach.c 项目: ArikaChen/lxc
struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid)
{
	struct lxc_proc_context_info *info = calloc(1, sizeof(*info));
	FILE *proc_file;
	char proc_fn[MAXPATHLEN];
	char *line = NULL;
	size_t line_bufsz = 0;
	int ret, found;

	if (!info) {
		SYSERROR("Could not allocate memory.");
		return NULL;
	}

	/* read capabilities */
	snprintf(proc_fn, MAXPATHLEN, "/proc/%d/status", pid);

	process_lock();
	proc_file = fopen(proc_fn, "r");
	process_unlock();
	if (!proc_file) {
		SYSERROR("Could not open %s", proc_fn);
		goto out_error;
	}

	found = 0;
	while (getline(&line, &line_bufsz, proc_file) != -1) {
		ret = sscanf(line, "CapBnd: %llx", &info->capability_mask);
		if (ret != EOF && ret > 0) {
			found = 1;
			break;
		}
	}

	if (line)
		free(line);
	process_lock();
	fclose(proc_file);
	process_unlock();

	if (!found) {
		SYSERROR("Could not read capability bounding set from %s", proc_fn);
		errno = ENOENT;
		goto out_error;
	}

	/* read personality */
	snprintf(proc_fn, MAXPATHLEN, "/proc/%d/personality", pid);

	process_lock();
	proc_file = fopen(proc_fn, "r");
	process_unlock();
	if (!proc_file) {
		SYSERROR("Could not open %s", proc_fn);
		goto out_error;
	}

	ret = fscanf(proc_file, "%lx", &info->personality);
	process_lock();
	fclose(proc_file);
	process_unlock();

	if (ret == EOF || ret == 0) {
		SYSERROR("Could not read personality from %s", proc_fn);
		errno = ENOENT;
		goto out_error;
	}
	info->lsm_label = lsm_process_label_get(pid);

	return info;

out_error:
	free(info);
	return NULL;
}
示例#30
0
文件: attach.c 项目: ArikaChen/lxc
char *lxc_attach_getpwshell(uid_t uid)
{
	/* local variables */
	pid_t pid;
	int pipes[2];
	int ret;
	int fd;
	char *result = NULL;

	/* we need to fork off a process that runs the
	 * getent program, and we need to capture its
	 * output, so we use a pipe for that purpose
	 */
	process_lock();
	ret = pipe(pipes);
	process_unlock();
	if (ret < 0)
		return NULL;

	pid = fork();
	if (pid < 0) {
		process_lock();
		close(pipes[0]);
		close(pipes[1]);
		process_unlock();
		return NULL;
	}

	if (pid) {
		/* parent process */
		FILE *pipe_f;
		char *line = NULL;
		size_t line_bufsz = 0;
		int found = 0;
		int status;

		process_lock();
		close(pipes[1]);
		process_unlock();

		process_lock();
		pipe_f = fdopen(pipes[0], "r");
		process_unlock();
		while (getline(&line, &line_bufsz, pipe_f) != -1) {
			char *token;
			char *saveptr = NULL;
			long value;
			char *endptr = NULL;
			int i;

			/* if we already found something, just continue
			 * to read until the pipe doesn't deliver any more
			 * data, but don't modify the existing data
			 * structure
			 */
			if (found)
				continue;

			/* trim line on the right hand side */
			for (i = strlen(line); i > 0 && (line[i - 1] == '\n' || line[i - 1] == '\r'); --i)
				line[i - 1] = '\0';

			/* split into tokens: first user name */
			token = strtok_r(line, ":", &saveptr);
			if (!token)
				continue;
			/* next: dummy password field */
			token = strtok_r(NULL, ":", &saveptr);
			if (!token)
				continue;
			/* next: user id */
			token = strtok_r(NULL, ":", &saveptr);
			value = token ? strtol(token, &endptr, 10) : 0;
			if (!token || !endptr || *endptr || value == LONG_MIN || value == LONG_MAX)
				continue;
			/* dummy sanity check: user id matches */
			if ((uid_t) value != uid)
				continue;
			/* skip fields: gid, gecos, dir, go to next field 'shell' */
			for (i = 0; i < 4; i++) {
				token = strtok_r(NULL, ":", &saveptr);
				if (!token)
					break;
			}
			if (!token)
				continue;
			if (result)
				free(result);
			result = strdup(token);

			/* sanity check that there are no fields after that */
			token = strtok_r(NULL, ":", &saveptr);
			if (token)
				continue;

			found = 1;
		}

		free(line);
		process_lock();
		fclose(pipe_f);
		process_unlock();
	again:
		if (waitpid(pid, &status, 0) < 0) {
			if (errno == EINTR)
				goto again;
			return NULL;
		}

		/* some sanity checks: if anything even hinted at going
		 * wrong: we can't be sure we have a valid result, so
		 * we assume we don't
		 */

		if (!WIFEXITED(status))
			return NULL;

		if (WEXITSTATUS(status) != 0)
			return NULL;

		if (!found)
			return NULL;

		return result;
	} else {
		/* child process */
		char uid_buf[32];
		char *arguments[] = {
			"getent",
			"passwd",
			uid_buf,
			NULL
		};

		process_unlock(); // we're no longer sharing
		close(pipes[0]);

		/* we want to capture stdout */
		dup2(pipes[1], 1);
		close(pipes[1]);

		/* get rid of stdin/stderr, so we try to associate it
		 * with /dev/null
		 */
		fd = open("/dev/null", O_RDWR);
		if (fd < 0) {
			close(0);
			close(2);
		} else {
			dup2(fd, 0);
			dup2(fd, 2);
			close(fd);
		}

		/* finish argument list */
		ret = snprintf(uid_buf, sizeof(uid_buf), "%ld", (long) uid);
		if (ret <= 0)
			exit(-1);

		/* try to run getent program */
		(void) execvp("getent", arguments);
		exit(-1);
	}
}