Exemplo n.º 1
0
static int interpret_table_entry(char *line, struct entry *root, off_t *fslen_ub)
{
	char type, *name = NULL;
	unsigned long mode = 0755, uid = 0, gid = 0, major = 0, minor = 0;
	unsigned long start = 0, increment = 1, count = 0;

	if (sscanf (line, "%" SCANF_PREFIX "s %c %lo %lu %lu %lu %lu %lu %lu %lu",
		 SCANF_STRING(name), &type, &mode, &uid, &gid, &major, &minor,
		 &start, &increment, &count) < 0) 
	{
		return 1;
	}

	if (!strcmp(name, "/")) {
		error_msg_and_die("Device table entries require absolute paths");
	}

	switch (type) {
	case 'd':
		mode |= S_IFDIR;
		modify_entry(name, uid, gid, mode, 0, root, fslen_ub);
		break;
	case 'f':
		mode |= S_IFREG;
		modify_entry(name, uid, gid, mode, 0, root, fslen_ub);
		break;
	case 'p':
		mode |= S_IFIFO;
		modify_entry(name, uid, gid, mode, 0, root, fslen_ub);
		break;
	case 'c':
	case 'b':
		mode |= (type == 'c') ? S_IFCHR : S_IFBLK;
		if (count > 0) {
			char *buf;
			unsigned long i;
			dev_t rdev;

			for (i = start; i < count; i++) {
				asprintf(&buf, "%s%lu", name, i);
				rdev = makedev(major, minor + (i * increment - start));
				modify_entry(buf, uid, gid, mode, rdev, root, fslen_ub);
				free(buf);
			}
		} else {
			dev_t rdev = makedev(major, minor);
			modify_entry(name, uid, gid, mode, rdev, root, fslen_ub);
		}
		break;
	default:
		error_msg_and_die("Unsupported file type");
	}
	free(name);
	return 0;
}
Exemplo n.º 2
0
void addFilespec(FILE *fd, int squash_uids, int squash_perms)
{

	unsigned long rmode, mode, uid, gid, major, minor, i;
	unsigned long start, increment, count, octmode, decmode;
	char *c, *dir, *name, *dname = NULL, *path = NULL, *path2 = NULL, *line = NULL;
	char type;
	size_t len;
	int argv, i2, overWrite = 0, lineno = 0;
	__u16 inodeType;

	while ( getline(&line, &len, fd) >= 0 ) {
		rmode = mode = uid = gid = major = minor = start = count = overWrite = 0;
		increment = 1;
		lineno++;

		if (( c = strchr(line, '#'))) *c = 0;
		if ( path ) {
			free( path ); path = NULL;
		}
		if ( path2 ) {
			free( path2 ); path2 = NULL;
		}

		argv = sscanf(line, "%" SCANF_PREFIX "s %c %ld %lu %lu %lu %lu %lu %lu %lu",
			      SCANF_STRING(path), &type, &rmode, &uid, &gid, &major, &minor,
			      &start, &increment, &count);

		if ( argv < 3 ) {
			if ( argv > 0 )
				log_warning("device table[%d]: bad format for entry '%s' [skip]", lineno, path);
			continue;
		}

		i2 = 0;
		octmode = rmode;
		decmode = 0;
		while ( octmode != 0 ) {
			decmode = decmode + (octmode % 10) * pow(8, i2++);
			octmode = octmode / 10;
		}

		if ( squash_uids ) uid = gid = 0;

		mode = decmode;
		path2 = strdup( path );
		name = basename( path );
		dir = dirname( path2 );

		if (( !strcmp(name, ".")) || ( !strcmp(name, "..")) || ( !strcmp(name, "/"))) {
			log_warning("device table[%d]: [skip]", lineno);
			continue;
		}

		log_action(ACT_CHDIR, dir, NULL, 0, 0, 0, 0, 0, 0, 0);
		if ( !do_chdir(dir)) {
			log_warning("device table[%d]: target directory '%s' for entry '%s' does not exist [skip]", lineno, dir, name);
			log_action(ACT_CHDIR, "/", NULL, 0, 0, 0, 0, 0, 0, 0);
			if ( !do_chdir("/"))
				log_error("[Filesystem error] cannot chdir to root");
			continue;
		}

		if (( type != 'd' ) && ( type != 'f' ) && ( type != 'p' ) && ( type != 'c' ) && ( type != 'b' ) && ( type != 's')) {
			log_warning("device table[%d]: bad type '%c' for entry '%s' [skip]", lineno, type, name);
			continue;
		}

		if (squash_perms) {
			mode &= ~( LINUX_S_IRWXG | LINUX_S_IRWXO );
			rmode &= ~( LINUX_S_IRWXG | LINUX_S_IRWXO);
		}

		if ( count > 0 ) {

			if ( dname ) {
				free( dname );
				dname = NULL;
			}

			unsigned len;
			len = strlen(name) + 10;
			dname = malloc(len + 1);

			for ( i = start; i < count; i++ ) {
				snprintf(dname, len, "%s%lu", name, i);

				if (( overWrite = name_to_inode(dname)))
					inodeType = inode_mode(dname);

				if (( type == 'd' ) && ( overWrite ) && ( !LINUX_S_ISDIR(inodeType)))
					log_error("[Remote fs mismatch] %s/%s exists but isn't a directory when it should be.", log_cwd(), dname);
				else if (( type != 'd' ) && ( overWrite )) {

					if ( LINUX_S_ISDIR(inodeType))
						log_error("[Remote fs mismatch] %s/%s exists but is a directory when it shouldn't be.", log_cwd(), dname);

					if ((!LINUX_S_ISREG(inodeType)) && (!LINUX_S_ISLNK(inodeType)) &&
					    (!LINUX_S_ISBLK(inodeType)) && (!LINUX_S_ISCHR(inodeType)) &&
					    (!LINUX_S_ISFIFO(inodeType)) && (!LINUX_S_ISSOCK(inodeType)))
						log_error("[Remote fs mismatch] Existing file %s/%s has unknown/unsupported type [0x%x].", log_cwd(), dname, inodeType);
				}

				switch ( type ) {
				case 'd':
					mode |= LINUX_S_IFDIR;
					log_action(ACT_MKDIR, dname, NULL, 0, 0, 0, 0, 0, 0, overWrite);

					if ( !overWrite )
						if ( !do_mkdir(dname))
							log_error("[Filesystem error] cannot mkdir %s/%s", log_cwd(), dname);

					break;

				case 'c':
				case 'b':
					if ( type == 'c' )
						mode |= LINUX_S_IFCHR;
					else
						mode |= LINUX_S_IFBLK;

					if ( overWrite ) {
						log_action(ACT_RM, dname, NULL, 0, 0, 0, 0, 0, 0, overWrite);
						if ( !do_rm(dname))
							log_error("[Filesystem error] cannot rm %s/%s", log_cwd(), dname);
					}

					log_action(ACT_MKNOD, dname, NULL, 0, 0, 0, type, major, minor + ((i * increment) - start), overWrite);
					if ( !do_mknod(dname, type, major, minor + ((i * increment) - start)))
						log_error("[Filesystem error] cannot mknod %s/%s", log_cwd(), dname);
					break;

				case 's':
				case 'p':
					if ( type == 's' )
						mode |= LINUX_S_IFSOCK;
					else mode |= LINUX_S_IFIFO;

					if ( overWrite ) {
						log_action(ACT_RM, dname, NULL, 0, 0, 0, 0, 0, 0, overWrite);
						if ( !do_rm(dname))
							log_error("[Filesystem error] cannot rm %s/%s", log_cwd(), dname);
					}

					log_action(ACT_MKNOD, dname, NULL, 0, 0, 0, type, 0, 0, overWrite);
					if ( !do_mknod(dname, type, 0, 0))
						log_error("[Filesystem error] cannot mknod %s/%s", log_cwd(), dname);

					break;
				}

				log_action(ACT_CHMOD, dname, NULL, rmode, 0, 0, 0, 0, 0, 0);
				if ( !do_chmod(dname, rmode))
					log_error("[Filesystem error] cannot chmod %s/%s", log_cwd(), dname);
				log_action(ACT_CHOWN, dname, NULL, 0, uid, gid, 0, 0, 0, 0);
				if ( !do_chown(dname, uid, gid))
					log_error("[Filesystem error] cannot chown %s/%s", log_cwd(), dname);
			}

			log_action(ACT_CHDIR, "/", NULL, 0, 0, 0, 0, 0, 0, 0);
			if ( !do_chdir("/"))
				log_error("[Filesystem error] cannot chdir to root");
			free(dname);
			dname = NULL;

		} else {

			if (( overWrite = name_to_inode(name)))
				inodeType = inode_mode(name);

			if (( type == 'd' ) && ( overWrite ) && ( !LINUX_S_ISDIR(inodeType)))
				log_error("[Remote fs mismatch] %s/%s exists but isn't a directory when it should be.", log_cwd(), dname);
			else if ( type != 'd' ) {
				if (( overWrite ) && ( LINUX_S_ISDIR(inodeType)))
					log_error("[Remote fs mismatch] %s/%s exists but is a directory when it shouldn't be.", log_cwd(), dname);

				if (( overWrite ) && (!LINUX_S_ISREG(inodeType)) && (!LINUX_S_ISLNK(inodeType)) &&
				    (!LINUX_S_ISBLK(inodeType)) && (!LINUX_S_ISCHR(inodeType)) &&
				    (!LINUX_S_ISFIFO(inodeType)) && (!LINUX_S_ISSOCK(inodeType)))
					log_error("[Remote fs mismatch] Existing file %s/%s has unknown/unsupported type [0x%x].",  log_cwd(), dname, inodeType);
			}

			switch ( type ) {
			case 'd':
				mode |= LINUX_S_IFDIR;
				log_action(ACT_MKDIR, name, NULL, 0, 0, 0, 0, 0, 0, overWrite);

				if ( !overWrite )
					if ( !do_mkdir(name))
						log_error("[Filesystem error] cannot mkdir %s/%s", log_cwd(), name);
				break;

			case 'c':
			case 'b':
				if ( type == 'c' )
					mode |= LINUX_S_IFCHR;
				else
					mode |= LINUX_S_IFBLK;

				if ( overWrite ) {
					log_action(ACT_RM, name, NULL, 0, 0, 0, 0, 0, 0, overWrite);
					if ( !do_rm(name))
						log_error("[Filesystem error] cannot rm %s/%s", log_cwd(), name);
				}

				log_action(ACT_MKNOD, name, NULL, 0, 0, 0, type, major, minor, overWrite);
				if ( !do_mknod(name, type, major, minor))
					log_error("[Filesystem error] cannot mknod %s/%s", log_cwd(), name);
				break;

			case 's':
			case 'p':
				if ( type == 's' )
					mode |= LINUX_S_IFSOCK;
				else mode |= LINUX_S_IFIFO;

				if ( overWrite ) {
					log_action(ACT_RM, name, NULL, 0, 0, 0, 0, 0, 0, overWrite);
					if ( !do_rm(name))
						log_error("[Filesystem error] cannot rm %s/%s", log_cwd(), name);
				}

				log_action(ACT_MKNOD, name, NULL, 0, 0, 0, type, 0, 0, overWrite);
				if ( !do_mknod(name, type, 0, 0))
					log_error("[Filesystem error] cannot mknod %s/%s", log_cwd(), name);
				break;
			}

			log_action(ACT_CHMOD, name, NULL, rmode, 0, 0, 0, 0, 0, 0);
			if ( !do_chmod(name, rmode))
				log_error("[Filesystem error] cannot chmod %s/%s", log_cwd(), name);
			log_action(ACT_CHOWN, name, NULL, 0, uid, gid, 0, 0, 0, 0);
			if ( !do_chown(name, uid, gid))
				log_error("[Filesystem error] cannot chown %s/%s", log_cwd(), name);
			log_action(ACT_CHDIR, "/", NULL, 0, 0, 0, 0, 0, 0, 0);
			if ( !do_chdir("/"))
				log_error("[Filesystem error] cannot chdir to root");
		}

	}


	if ( line ) {
		free( line ); line = NULL;
	}
	if ( path ) {
		free( path ); path = NULL;
	}
	if ( path2 ) {
		free( path2 ); path2 = NULL;
	}

}
Exemplo n.º 3
0
/*  device table entries take the form of:
    <path>	<type> <mode>	<uid>	<gid>	<major>	<minor>	<start>	<inc>	<count>
    /dev/mem     c    640       0       0         1       1       0     0         -

    type can be one of:
	f	A regular file
	d	Directory
	c	Character special device file
	b	Block special device file
	p	Fifo (named pipe)

    I don't bother with symlinks (permissions are irrelevant), hard
    links (special cases of regular files), or sockets (why bother).

    Regular files must exist in the target root directory.  If a char,
    block, fifo, or directory does not exist, it will be created.
*/
static int interpret_table_entry(struct filesystem_entry *root, char *line)
{
	char *hostpath;
	char type, *name = NULL, *tmp, *dir;
	unsigned long mode = 0755, uid = 0, gid = 0, major = 0, minor = 0;
	unsigned long start = 0, increment = 1, count = 0;
	struct filesystem_entry *parent, *entry;

	if (sscanf (line, "%" SCANF_PREFIX "s %c %lo %lu %lu %lu %lu %lu %lu %lu",
		 SCANF_STRING(name), &type, &mode, &uid, &gid, &major, &minor,
		 &start, &increment, &count) < 0)
	{
		return 1;
	}

	if (!strcmp(name, "/")) {
		error_msg_and_die("Device table entries require absolute paths");
	}

	asprintf(&hostpath, "%s%s", rootdir, name);

	/* Check if this file already exists... */
	switch (type) {
		case 'd':
			mode |= S_IFDIR;
			break;
		case 'f':
			mode |= S_IFREG;
			break;
		case 'p':
			mode |= S_IFIFO;
			break;
		case 'c':
			mode |= S_IFCHR;
			break;
		case 'b':
			mode |= S_IFBLK;
			break;
		default:
			error_msg_and_die("Unsupported file type");
	}
	entry = find_filesystem_entry(root, name, mode);
	if (entry) {
		/* Ok, we just need to fixup the existing entry
		 * and we will be all done... */
		entry->sb.st_uid = uid;
		entry->sb.st_gid = gid;
		entry->sb.st_mode = mode;
		if (major && minor) {
			entry->sb.st_rdev = makedev(major, minor);
		}
	} else {
		/* If parent is NULL (happens with device table entries),
		 * try and find our parent now) */
		tmp = strdup(name);
		dir = dirname(tmp);
		parent = find_filesystem_entry(root, dir, S_IFDIR);
		free(tmp);
		if (parent == NULL) {
			error_msg ("skipping device_table entry '%s': no parent directory!", name);
			free(name);
			free(hostpath);
			return 1;
		}

		switch (type) {
			case 'd':
				add_host_filesystem_entry(name, hostpath, uid, gid, mode, 0, parent);
				break;
			case 'f':
				add_host_filesystem_entry(name, hostpath, uid, gid, mode, 0, parent);
				break;
			case 'p':
				add_host_filesystem_entry(name, hostpath, uid, gid, mode, 0, parent);
				break;
			case 'c':
			case 'b':
				if (count > 0) {
					dev_t rdev;
					unsigned long i;
					char *dname, *hpath;

					for (i = start; i < count; i++) {
						asprintf(&dname, "%s%lu", name, i);
						asprintf(&hpath, "%s/%s%lu", rootdir, name, i);
						rdev = makedev(major, minor + (i * increment - start));
						add_host_filesystem_entry(dname, hpath, uid, gid,
								mode, rdev, parent);
						free(dname);
						free(hpath);
					}
				} else {
					dev_t rdev = makedev(major, minor);
					add_host_filesystem_entry(name, hostpath, uid, gid,
							mode, rdev, parent);
				}
				break;
			default:
				error_msg_and_die("Unsupported file type");
		}
	}
	free(name);
	free(hostpath);
	return 0;
}