From 057ab92dfee57905800e177577ca488f02be0117 Mon Sep 17 00:00:00 2001 From: Jakub Martisko Date: Thu, 23 Nov 2017 10:09:08 +0100 Subject: [PATCH] sed: with --in-place and selinux, use the symlink's context When editing a file in place, the SELinux context (if exists) should be based on the link instead of the target file itself. --follow-symlinks option remains unchanged. Bug reported by Jakub Jelen, fix proposed by Petr Lautrbach, discussed in https://lists.gnu.org/r/sed-devel/2017-12/msg00000.html * NEWS: Mention this. * sed/execute.c (open_next_file): Use lgetfilecon (instead of getfilecon) to get the context of the symlink instead of the target file. * testsuite/inplace-selinux.sh: Test the above change. * testsuite/local.mk (T): Add new test file. * init.cfg (require_selinux_): Copied from coreutils, skip the test if selinux is not available. --- NEWS | 4 ++++ init.cfg | 21 +++++++++++++++++++ sed/execute.c | 2 +- testsuite/inplace-selinux.sh | 49 ++++++++++++++++++++++++++++++++++++++++++++ testsuite/local.mk | 1 + 5 files changed, 76 insertions(+), 1 deletion(-) create mode 100755 testsuite/inplace-selinux.sh diff --git a/NEWS b/NEWS index e9335f0..e762b2d 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,10 @@ GNU sed NEWS -*- outline -*- [Bug introduced in the original implementation of --posix option in v4.1a-5-gba68fb4] + sed -i now creates selinux context based on the context of the symlink + instead of the symlink target. [Bug present since at least sed-4.2] + sed -i --follow-symlinks remains unchanged. + * Noteworthy changes in release 4.4 (2017-02-03) [stable] diff --git a/init.cfg b/init.cfg index fc3a5f7..a30dbb8 100644 --- a/init.cfg +++ b/init.cfg @@ -131,3 +131,24 @@ remove_cr_inplace() { sed -i -e "s/\r//g" "$@" || framework_failure_ } + +require_selinux_() +{ + # When in a chroot of an SELinux-enabled system, but with a mock-simulated + # SELinux-*disabled* system, recognize that SELinux is disabled system wide: + grep 'selinuxfs$' /proc/filesystems > /dev/null \ + || skip_ "this system lacks SELinux support" + + # Independent of whether SELinux is enabled system-wide, + # the current file system may lack SELinux support. + # Also the current build may have SELinux support disabled. + case $(ls -Zd .) in + '? .'|'unlabeled .') + test -z "$CONFIG_HEADER" \ + && framework_failure_ 'CONFIG_HEADER not defined' + grep '^#define HAVE_SELINUX_SELINUX_H 1' "$CONFIG_HEADER" > /dev/null \ + && selinux_missing_="(file) system" || selinux_missing_="build" + skip_ "this $selinux_missing_ lacks SELinux support" + ;; + esac +} diff --git a/sed/execute.c b/sed/execute.c index 1843392..453886e 100644 --- a/sed/execute.c +++ b/sed/execute.c @@ -607,7 +607,7 @@ open_next_file(const char *name, struct input *input) if (is_selinux_enabled () > 0) { security_context_t con; - if (getfilecon (input->in_file_name, &con) != -1) + if (lgetfilecon (input->in_file_name, &con) != -1) { /* Save and restore the old context for the sake of w and W commands. */ diff --git a/testsuite/inplace-selinux.sh b/testsuite/inplace-selinux.sh new file mode 100755 index 0000000..ac315f5 --- /dev/null +++ b/testsuite/inplace-selinux.sh @@ -0,0 +1,49 @@ +#!/bin/sh + +# Copyright (C) 2017 Free Software Foundation, Inc. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +. "${srcdir=.}/testsuite/init.sh"; path_prepend_ ./sed +print_ver_ sed +require_selinux_ + +fail=0 + +# Create the first file and symlink pointing at it. +echo "Hello World" > inplace-selinux-file || framework_failure_ +ln -s ./inplace-selinux-file inplace-selinux-link || framework_failure_ + +chcon -h -t user_home_t inplace-selinux-file || framework_failure_ +chcon -h -t user_tmp_t inplace-selinux-link || framework_failure_ + + +# Create the second file and symlink pointing at it. +# These will be used with the --follow-symlink option. +echo "Hello World" > inplace-selinux-file2 || framework_failure_ +ln -s ./inplace-selinux-file2 inplace-selinux-link2 || framework_failure_ + +chcon -h -t user_home_t inplace-selinux-file2 || framework_failure_ +chcon -h -t user_tmp_t inplace-selinux-link2 || framework_failure_ + +# Modify prepared files inplace via the symlinks +sed -i -e "s~Hello~Hi~" inplace-selinux-link || fail=1 +sed -i --follow-symlinks -e "s~Hello~Hi~" inplace-selinux-link2 || fail=1 + +# Check selinux context - the first file should be created with the context +# of the symlink... +ls -Z inplace-selinux-link | grep ':user_tmp_t:' || fail=1 +# ...the second file should use the context of the file itself. +ls -Z inplace-selinux-file2 | grep ':user_home_t:' || fail=1 + +Exit $fail diff --git a/testsuite/local.mk b/testsuite/local.mk index 8c6d63f..fe47b92 100644 --- a/testsuite/local.mk +++ b/testsuite/local.mk @@ -52,6 +52,7 @@ T = \ testsuite/help-version.sh \ testsuite/in-place-hyphen.sh \ testsuite/in-place-suffix-backup.sh \ + testsuite/inplace-selinux.sh \ testsuite/invalid-mb-seq-UMR.sh \ testsuite/mb-bad-delim.sh \ testsuite/mb-charclass-non-utf8.sh \ -- 2.7.4