selinux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Test to trace kernel bug in fsconfig(2) with btrfs
@ 2020-02-06  9:50 Richard Haines
  0 siblings, 0 replies; only message in thread
From: Richard Haines @ 2020-02-06  9:50 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: selinux, dhowells, viro, sds, paul, omosnace

[-- Attachment #1: Type: text/plain, Size: 1285 bytes --]

I've attached a test program 'fsmount.c'. This can be used along with
the test script below to show a kernel bug when calling fsconfig(2)
with security options on a btrfs filesystem.

This problem only occurs using fsconfig(2) when attempting to add
security options. Setting a native btrfs option (e.g. flushoncommit)
works.

Copy the statements below into test.sh and run with the fs name. Other
fs will work such as ext4, xfs. Only btrfs will fail.

#!/bin/sh
fs_name=$1

mkdir -p /mnt/selinux-testsuite
dd if=/dev/zero of=./fstest bs=4096 count=27904
dev=`losetup -f`
losetup $dev ./fstest
mkfs.$fs_name $dev
/usr/bin/systemctl stop udisks2 # Stops crap appearing in journal log
# mount(2) works:
#mount -t $fs_name -o "rootcontext=system_u:object_r:unconfined_t:s0"
$dev /mnt/selinux-testsuite
# This native btrfs "flushoncommit" option will work with fsconfig(2):
#./fsmount $fs_name $dev  /mnt/selinux-testsuite "flushoncommit"
# This will not:
./fsmount $fs_name $dev  /mnt/selinux-testsuite
"rootcontext=system_u:object_r:unconfined_t:s0"
# rootcontext fails with journal entry: SELinux: mount invalid.
#    Same superblock, different security settings for (dev loop0, type
btrfs)
umount /mnt/selinux-testsuite
losetup -d $dev
/usr/bin/systemctl start udisks2
rm -f ./fstest


[-- Attachment #2: fsmount.c --]
[-- Type: text/x-csrc, Size: 2727 bytes --]

/* cc fsmount.c -o fsmount -Wall */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/prctl.h>
#include <linux/mount.h>
#include <linux/unistd.h>

int fsopen(const char *fs_name, unsigned int flags)
{
	return syscall(__NR_fsopen, fs_name, flags);
}

int fsconfig(int fsfd, unsigned int cmd, const char *key,
	     const void *val, int aux)
{
	return syscall(__NR_fsconfig, fsfd, cmd, key, val, aux);
}

int fsmount(int fsfd, unsigned int flags, unsigned int ms_flags)
{
	return syscall(__NR_fsmount, fsfd, flags, ms_flags);
}

int move_mount(int from_dfd, const char *from_pathname, int to_dfd,
	       const char *to_pathname, unsigned int flags)
{
	return syscall(__NR_move_mount, from_dfd, from_pathname,
		       to_dfd, to_pathname, flags);
}

#define MAX_OPS 10
int fsconfig_opts(int fd, char *src, char *opts)
{
	int ret, i, max_entries = 0;
	int cmd[MAX_OPS];
	char *key[MAX_OPS], *value[MAX_OPS];
	char *src_str = "source";

	cmd[0] = FSCONFIG_SET_STRING;
	key[0] = src_str;
	value[0] = src;

	for (i = 1; i < MAX_OPS; i++) {
		value[i] = strsep(&opts, ",");
		if (!value[i]) {
			max_entries = i + 1;
			break;
		}
		cmd[i] = FSCONFIG_SET_STRING;
	}

	for (i = 1; value[i] != NULL; i++) {
		key[i] = strsep(&value[i], "=");
		if (!value[i])
			cmd[i] = FSCONFIG_SET_FLAG;
	}

	cmd[i] = FSCONFIG_CMD_CREATE;
	key[i] = NULL;
	value[i] = NULL;

	for (i = 0; i != max_entries; i++) {
		printf("fsconfig(0x%x, %s, %s, 0)\n", cmd[i], key[i], value[i]);
		ret = fsconfig(fd, cmd[i], key[i], value[i], 0);
		if (ret < 0) {
			fprintf(stderr, "Failed fsconfig(2): %s\n",
				strerror(errno));
			return -1;
		}
	}
	return 0;
}

int main(int argc, char *argv[])
{
	int ret, fsfd, mfd;
	unsigned int mount_attrs = 0;
	char *opts;

	if (argc != 5) {
		fprintf(stderr, "usage: %s <type> <src> <tgt> <opts>\n", argv[0]);
		return 1;
	}

	fsfd = fsopen(argv[1], 0);
	if (fsfd < 0) {
		fprintf(stderr, "Failed fsopen(2): %s\n", strerror(errno));
		return -1;
	}

	if (!strncmp (argv[1], "nfs", 3))
		mount_attrs = MS_NODEV;

	opts = strdup(argv[4]);

	ret = fsconfig_opts(fsfd, argv[2], opts);
	if (ret < 0) {
		fprintf(stderr, "Failed to add options: %s\n", argv[4]);
		close(fsfd);
		return -1;
	}
	printf("Successfully added options: %s\n", argv[4]);

	mfd = fsmount(fsfd, 0, mount_attrs);
	if (mfd < 0) {
		fprintf(stderr, "Failed fsmount(2): %s\n", strerror(errno));
		return -1;
	}
	close(fsfd);

	ret = move_mount(mfd, "", AT_FDCWD, argv[3], MOVE_MOUNT_F_EMPTY_PATH);
	if (ret < 0) {
		fprintf(stderr, "Failed move_mount(2): %s\n", strerror(errno));
		return -1;
	}
	close(mfd);

	printf("Successfully mounted on: %s\n", argv[3]);

	return 0;
}

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2020-02-06  9:50 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-06  9:50 Test to trace kernel bug in fsconfig(2) with btrfs Richard Haines

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).