selinux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Richard Haines <richard_c_haines@btinternet.com>
To: linux-fsdevel@vger.kernel.org
Cc: selinux@vger.kernel.org, dhowells@redhat.com,
	viro@zeniv.linux.org.uk, sds@tycho.nsa.gov, paul@paul-moore.com,
	omosnace@redhat.com
Subject: Test to trace kernel bug in fsconfig(2) with btrfs
Date: Thu, 06 Feb 2020 09:50:46 +0000	[thread overview]
Message-ID: <c02674c970fa292610402aa866c4068772d9ad4e.camel@btinternet.com> (raw)

[-- 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;
}

                 reply	other threads:[~2020-02-06  9:50 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=c02674c970fa292610402aa866c4068772d9ad4e.camel@btinternet.com \
    --to=richard_c_haines@btinternet.com \
    --cc=dhowells@redhat.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=omosnace@redhat.com \
    --cc=paul@paul-moore.com \
    --cc=sds@tycho.nsa.gov \
    --cc=selinux@vger.kernel.org \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).