Re: [PATCH] Smack modifications for: security: Allow all LSMs to provide xattrs for inode_init_security hook

Casey Schaufler <[email protected]>
Newsgroups gmane.linux.kernel.bpf,gmane.comp.file-systems.reiserfs.general,gmane.linux.kernel,gmane.linux.kernel.lsm
Message-ID <[email protected]>
On 4/18/2023 12:05 AM, Roberto Sassu wrote:
> On Mon, 2023-04-17 at 09:41 -0700, Casey Schaufler wrote:
>> On 4/13/2023 12:11 AM, Roberto Sassu wrote:
>>> On Wed, 2023-04-12 at 13:29 -0700, Casey Schaufler wrote:
>>>> On 4/12/2023 12:22 AM, Roberto Sassu wrote:
>>>>> On Tue, 2023-04-11 at 10:54 -0700, Casey Schaufler wrote:
>>>>>> On 4/11/2023 10:23 AM, Roberto Sassu wrote:
>>>>>>> From: Roberto Sassu <[email protected]>
>>>>>>>
>>>>>>> Very very quick modification. Not tested.
>>>>>>>
>>>>>>> Signed-off-by: Roberto Sassu <[email protected]>
>>>>>>> ---
>>>>>>>  security/smack/smack.h     |  2 +-
>>>>>>>  security/smack/smack_lsm.c | 42 ++++++++++++++++++++------------------
>>>>>>>  2 files changed, 23 insertions(+), 21 deletions(-)
>>>>>>>
>>>>>>> diff --git a/security/smack/smack.h b/security/smack/smack.h
>>>>>>> index e2239be7bd6..f00c8498c60 100644
>>>>>>> --- a/security/smack/smack.h
>>>>>>> +++ b/security/smack/smack.h
>>>>>>> @@ -127,7 +127,7 @@ struct task_smack {
>>>>>>>  
>>>>>>>  #define	SMK_INODE_INSTANT	0x01	/* inode is instantiated */
>>>>>>>  #define	SMK_INODE_TRANSMUTE	0x02	/* directory is transmuting */
>>>>>>> -#define	SMK_INODE_CHANGED	0x04	/* smack was transmuted */
>>>>>>> +#define	SMK_INODE_CHANGED	0x04	/* smack was transmuted (unused) */
>>>>>> See below ...
>>>>>>
>>>>>>>  #define	SMK_INODE_IMPURE	0x08	/* involved in an impure transaction */
>>>>>>>  
>>>>>>>  /*
>>>>>>> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
>>>>>>> index 8392983334b..b43820bdbd0 100644
>>>>>>> --- a/security/smack/smack_lsm.c
>>>>>>> +++ b/security/smack/smack_lsm.c
>>>>>>> @@ -54,12 +54,12 @@
>>>>>>>  
>>>>>>>  /*
>>>>>>>   * Smack uses multiple xattrs.
>>>>>>> - * SMACK64 - for access control, SMACK64EXEC - label for the program,
>>>>>>> - * SMACK64MMAP - controls library loading,
>>>>>>> + * SMACK64 - for access control,
>>>>>>>   * SMACK64TRANSMUTE - label initialization,
>>>>>>> - * Not saved on files - SMACK64IPIN and SMACK64IPOUT
>>>>>>> + * Not saved on files - SMACK64IPIN and SMACK64IPOUT,
>>>>>>> + * Must be set explicitly - SMACK64EXEC and SMACK64MMAP
>>>>>>>   */
>>>>>>> -#define SMACK_INODE_INIT_XATTRS 4
>>>>>>> +#define SMACK_INODE_INIT_XATTRS 2
>>>>>>>  
>>>>>>>  #ifdef SMACK_IPV6_PORT_LABELING
>>>>>>>  static DEFINE_MUTEX(smack_ipv6_lock);
>>>>>>> @@ -957,11 +957,11 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
>>>>>>>  				     const struct qstr *qstr,
>>>>>>>  				     struct xattr *xattrs, int *xattr_count)
>>>>>>>  {
>>>>>>> -	struct inode_smack *issp = smack_inode(inode);
>>>>>>>  	struct smack_known *skp = smk_of_current();
>>>>>>>  	struct smack_known *isp = smk_of_inode(inode);
>>>>>>>  	struct smack_known *dsp = smk_of_inode(dir);
>>>>>>>  	struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count);
>>>>>>> +	struct xattr *xattr2;
>>>>>> I'm going to channel Paul and suggest this be xattr_transmute instead of xattr2.
>>>>>> It also looks like it could move to be declared in the if clause.
>>>>>>
>>>>>>>  	int may;
>>>>>>>  
>>>>>>>  	if (xattr) {
>>>>>>> @@ -979,7 +979,17 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
>>>>>>>  		if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
>>>>>>>  		    smk_inode_transmutable(dir)) {
>>>>>>>  			isp = dsp;
>>>>>>> -			issp->smk_flags |= SMK_INODE_CHANGED;
>>>>>> I think you need to keep this. More below.
>>>>>>
>>>>>>> +			xattr2 = lsm_get_xattr_slot(xattrs, xattr_count);
>>>>>>> +			if (xattr2) {
>>>>>>> +				xattr2->value = kmemdup(TRANS_TRUE,
>>>>>>> +							TRANS_TRUE_SIZE,
>>>>>>> +							GFP_NOFS);
>>>>>>> +				if (xattr2->value == NULL)
>>>>>>> +					return -ENOMEM;
>>>>>>> +
>>>>>>> +				xattr2->value_len = TRANS_TRUE_SIZE;
>>>>>>> +				xattr2->name = XATTR_NAME_SMACKTRANSMUTE;
>>>>>>> +			}
>>>>>>>  		}
>>>>>>>  
>>>>>>>  		xattr->value = kstrdup(isp->smk_known, GFP_NOFS);
>>>>>>> @@ -3512,20 +3522,12 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
>>>>>>>  			 * If there is a transmute attribute on the
>>>>>>>  			 * directory mark the inode.
>>>>>>>  			 */
>>>>>>> -			if (isp->smk_flags & SMK_INODE_CHANGED) {
>>>>>>> -				isp->smk_flags &= ~SMK_INODE_CHANGED;
>>>>>>> -				rc = __vfs_setxattr(&nop_mnt_idmap, dp, inode,
>>>>>>> -					XATTR_NAME_SMACKTRANSMUTE,
>>>>>>> -					TRANS_TRUE, TRANS_TRUE_SIZE,
>>>>>>> -					0);
>>>>>>> -			} else {
>>>>>>> -				rc = __vfs_getxattr(dp, inode,
>>>>>>> -					XATTR_NAME_SMACKTRANSMUTE, trattr,
>>>>>>> -					TRANS_TRUE_SIZE);
>>>>>>> -				if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
>>>>>>> -						       TRANS_TRUE_SIZE) != 0)
>>>>>>> -					rc = -EINVAL;
>>>>>>> -			}
>>>>>>> +			rc = __vfs_getxattr(dp, inode,
>>>>>>> +					    XATTR_NAME_SMACKTRANSMUTE, trattr,
>>>>>>> +					    TRANS_TRUE_SIZE);
>>>>>>> +			if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
>>>>>>> +					       TRANS_TRUE_SIZE) != 0)
>>>>>>> +				rc = -EINVAL;
>>>>>> Where is the SMACK64_TRANSMUTE attribute going to get set on the file?
>>>>>> It's not going to get set in smack_init_inode_security(). The inode will
>>>>> Isn't that the purpose of the inode_init_security hook?
>>>> No. It initializes the in-memory inode. 
>>> I hope I'm not mistaken here...
>>>
>>> I make a small example. Filesystems call
>>> security_inode_init_security(). Ext4 does:
>>>
>>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/ext4/xattr_security.c?h=v6.3-rc6#n54
>>>
>>> security_inode_init_security() allocates new_xattrs. Each LSM fills
>>> new_xattrs. At the end of the loop, if there is at least one xattr
>>> filled, the initxattrs() callback passed by the caller of
>>> security_inode_init_security() is called.
>>>
>>> The ext4 initxattrs() callback is:
>>>
>>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/ext4/xattr_security.c?h=v6.3-rc6#n35
>>>
>>> which scans the xattr array and, for each xattr,
>>> calls ext4_xattr_set_handle().
>>>
>>> Maybe I'm overlooking it, but ext4_xattr_set_handle() is setting xattrs
>>> on the disk. Am I wrong?
>> Yes, you're wrong. I tried your change, and the SMACK64_TRANSMUTE isn't
>> set on the sub-directory when it's created. The __vfs_setxattr() call really
>> is necessary. 
> Could you please also check if there is any change with this fix:
>
> Replace:
>
> 	xattr2->name = XATTR_NAME_SMACKTRANSMUTE;
>
> with:
>
> 	xattr2->name = XATTR_SMACK_TRANSMUTE;
>
> Thanks

Unless I'm missing something really obvious there's no way that any
of the evm/ima changes would obviate the need for the __vfs_setxattr() call.
It's real easy to verify correct behavior, see the attached script.
(you'll want to change the "notroot" value to a user on your system)

>
> Roberto
>
>>> Thanks
>>>
>>> Roberto
>>>
>>>>> After all LSMs provide one or multiple xattrs, xattrs are going to be
>>>>> written to the disk with the initxattr() callback of filesystems.
>>>>>
>>>>> There is a small mistake above (XATTR_SMACK_TRANSMUTE instead
>>>>> of XATTR_NAME_SMACKTRANSMUTE, as we are providing just the suffix).
>>>> but I'm pretty sure the __vfs_setxattr() call is necessary to get
>>>> the attribute written out. With your change the in-memory inode will
>>>> get the attribute, but if you reboot it won't be on the directory.
>>>>
>>>>> 95 Passed, 0 Failed, 100% Success rate
>>>>>
>>>>> There was a test failing in dir-transmute.sh, before I fixed the xattr
>>>>> name.
>>>>>
>>>>> Thanks
>>>>>
>>>>> Roberto
>>>>>
>>>>>> know it's transmuting, but it won't get to disk without the __vfs_setxattr()
>>>>>> here in smack_d_instantiate(). Now, it's been a long time since that code
>>>>>> was written, so I could be wrong, but I'm pretty sure about that.
>>>>>>
>>>>>> I think that you should be fine with the changes in smack_init_inode_security(),
>>>>>> and leaving smack_d_instantiate() untouched. 
>>>>>>
>>>>>>>  			if (rc >= 0)
>>>>>>>  				transflag = SMK_INODE_TRANSMUTE;
>>>>>>>  		}
testtransmute.sh (text/plain, 9.5 KB)
#! /bin/sh
#
#

TESTDIR="/tmp/transmute-test"
TESTFILE="$TESTDIR"/file
TESTSUBDIR="$TESTDIR"/subdir
TESTSUB2DIR="$TESTSUBDIR"/subdir
TESTSUB3DIR="$TESTSUB2DIR"/subdir
USERID=`/usr/bin/id -u`
LOAD=/sys/fs/smackfs/load2

if [ "$USERID" != "0" ]
then
	echo User ID $USERID is not root.
	exit 1
fi

notroot="cschaufler"
# NOTROOT=`tail -1 /etc/passwd | sed -e 's/:.*//'`
# echo Using '"'$NOTROOT'"' as a test user.

RUNAS=`cat /proc/self/attr/current`

rm -rf $TESTDIR
mkdir $TESTDIR
grep `cat /proc/self/attr/current` $LOAD
echo Dir: `attr -q -S -g SMACK64 $TESTDIR 2> /dev/null` `ls -id $TESTDIR` `attr -q -S -g SMACK64TRANSMUTE $TESTDIR 2> /dev/null`

#
# Simple set/list/get tests
#
TLABEL=`attr -q -S -g SMACK64TRANSMUTE $TESTDIR 2> /dev/null`
if [ "x""$TLABEL" != "x" ]
then
	echo Initial transmute label is unexpectedly '"'"$TLABEL"'"'.
	exit 1
fi

attr -q -S -s SMACK64TRANSMUTE -V WILL $TESTDIR 2> /dev/null
TLABEL=`attr -q -S -g SMACK64TRANSMUTE $TESTDIR 2> /dev/null`
if [ "x""$TLABEL" != "x" ]
then
	echo Setting transmute label should not have gotten '"'"$TLABEL"'"'.
	exit 1
fi

TLIST=`attr -q -S -l $TESTDIR | grep TRANSMUTE`
if [ "x""$TLIST" != "x" ]
then
	echo Setting transmute label listed incorrectly as '"'"$TLIST"'"'.
	exit 1
fi

attr -q -S -s SMACK64TRANSMUTE -V TRUE $TESTDIR 2> /dev/null
TLABEL=`attr -q -S -g SMACK64TRANSMUTE $TESTDIR 2> /dev/null`
if [ "x""$TLABEL" != "xTRUE" ]
then
	echo Setting transmute label should not have gotten '"'"$TLABEL"'"'.
	exit 1
fi

TLIST=`attr -q -S -l $TESTDIR | grep TRANSMUTE`
if [ "x""$TLIST" != "xSMACK64TRANSMUTE" ]
then
	echo Setting transmute label listed incorrectly as '"'"$TLIST"'"'.
	exit 1
fi

attr -q -S -r SMACK64TRANSMUTE $TESTDIR 2> /dev/null
TLABEL=`attr -q -S -g SMACK64TRANSMUTE $TESTDIR 2> /dev/null`
if [ "x""$TLABEL" != "x" ]
then
	echo Removing transmute label left '"'"$TLABEL"'"' behind.
	exit 1
fi

rm -rf $TESTDIR

#
# Rule setting tests
#
#          1         2         3         4         5         6
# 1234567890123456789012345678901234567890123456789012345678901234567890
# subject-label.......... object-label........... rwxat
#

#                 1         2         3
#        123456789012345678901234567890
SUBJECT="Snap                   "
SUBNAME="Snap"

#                1         2         3
#       123456789012345678901234567890
OBJECT="Crackle                "
OBNAME="Crackle"

OLDRULE=`grep '^'"$SUBNAME"' '"$OBNAME" $LOAD`

echo -n "$SUBJECT"' '"$OBJECT"' ''rwxa' > $LOAD
RULE=`grep '^'"$SUBNAME"' '"$OBNAME" $LOAD`
if [ "x""$RULE" != "x""$SUBNAME"' '"$OBNAME"' rwxa' ]
then
	echo Setting rule without '"'t'"' unexpectedly '"'"$RULE"'"'.
	exit 1
fi

echo -n "$SUBJECT"' '"$OBJECT"' ''rwxat' > $LOAD
RULE=`grep '^'"$SUBNAME"' '"$OBNAME" $LOAD`
if [ "x""$RULE" != "x""$SUBNAME"' '"$OBNAME"' rwxat' ]
then
	echo Setting rule with '"'t'"' unexpectedly '"'"$RULE"'"'.
	exit 1
fi

#
# Verify correct label behavior with neither a transmute
# directory nor a transmute rule.
#

rm -rf $TESTDIR
mkdir $TESTDIR
grep `cat /proc/self/attr/current` $LOAD
echo Dir: `attr -q -S -g SMACK64 $TESTDIR 2> /dev/null` `ls -id $TESTDIR` `attr -q -S -g SMACK64TRANSMUTE $TESTDIR 2> /dev/null`
chmod 777 $TESTDIR
attr -q -S -s SMACK64 -V $OBNAME $TESTDIR
echo -n "$SUBJECT"' '"$OBJECT"' ''rwxa' > $LOAD

echo "$SUBNAME" > /proc/self/attr/current
su - $NOTROOT -c "date > $TESTFILE"
echo "$RUNAS" > /proc/self/attr/current
GOT=`attr -q -S -g SMACK64 $TESTFILE`

if [ 'x'"$SUBNAME" != 'x'"$GOT" ]
then
	echo Expected '"'$SUBNAME'"' but got '"'$GOT'"'.
	exit 1
fi

#
# Verify correct label behavior with a transmute
# directory but not a transmute rule.
#

rm -rf $TESTDIR
mkdir $TESTDIR
grep `cat /proc/self/attr/current` $LOAD
echo Dir: `attr -q -S -g SMACK64 $TESTDIR 2> /dev/null` `ls -id $TESTDIR` `attr -q -S -g SMACK64TRANSMUTE $TESTDIR 2> /dev/null`
chmod 777 $TESTDIR
attr -q -S -s SMACK64 -V $OBNAME $TESTDIR
attr -q -S -s SMACK64TRANSMUTE -V TRUE $TESTDIR
echo -n "$SUBJECT"' '"$OBJECT"' ''rwxa' > $LOAD

echo "$SUBNAME" > /proc/self/attr/current
su - $NOTROOT -c "date > $TESTFILE"
echo "$RUNAS" > /proc/self/attr/current
GOT=`attr -q -S -g SMACK64 $TESTFILE`

if [ 'x'"$SUBNAME" != 'x'"$GOT" ]
then
	echo Expected '"'$SUBNAME'"' but got '"'$GOT'"'.
	exit 1
fi

#
# Verify correct label behavior without  a transmute
# directory but with a transmute rule.
#

rm -rf $TESTDIR
mkdir $TESTDIR
grep `cat /proc/self/attr/current` $LOAD
echo Dir: `attr -q -S -g SMACK64 $TESTDIR 2> /dev/null` `ls -id $TESTDIR` `attr -q -S -g SMACK64TRANSMUTE $TESTDIR 2> /dev/null`
chmod 777 $TESTDIR
attr -q -S -s SMACK64 -V $OBNAME $TESTDIR
echo -n "$SUBJECT"' '"$OBJECT"' ''rwxat' > $LOAD

echo "$SUBNAME" > /proc/self/attr/current
su - $NOTROOT -c "date > $TESTFILE"
echo "$RUNAS" > /proc/self/attr/current
GOT=`attr -q -S -g SMACK64 $TESTFILE`

if [ 'x'"$SUBNAME" != 'x'"$GOT" ]
then
	echo Expected '"'$SUBNAME'"' but got '"'$GOT'"'.
	exit 1
fi

#
# Verify correct label behavior with a transmute
# directory and a transmute rule.
#

rm -rf $TESTDIR
mkdir $TESTDIR
grep `cat /proc/self/attr/current` $LOAD
echo Dir: `attr -q -S -g SMACK64 $TESTDIR 2> /dev/null` `ls -id $TESTDIR` `attr -q -S -g SMACK64TRANSMUTE $TESTDIR 2> /dev/null`
chmod 777 $TESTDIR
attr -q -S -s SMACK64 -V $OBNAME $TESTDIR
attr -q -S -s SMACK64TRANSMUTE -V TRUE $TESTDIR
grep `cat /proc/self/attr/current` $LOAD
echo Dir: `attr -q -S -g SMACK64 $TESTDIR 2> /dev/null` `ls -id $TESTDIR` `attr -q -S -g SMACK64TRANSMUTE $TESTDIR 2> /dev/null`
echo -n "$SUBJECT"' '"$OBJECT"' ''rwxat' > $LOAD

echo "$SUBNAME" > /proc/self/attr/current
su - $NOTROOT -c "date > $TESTFILE"
echo "$RUNAS" > /proc/self/attr/current
GOT=`attr -q -S -g SMACK64 $TESTFILE`

if [ 'x'"$OBNAME" != 'x'"$GOT" ]
then
	echo Expected '"'$OBNAME'"' but got '"'$GOT'"'.
	attr -l -S $TESTDIR
	attr -S -g SMACK64 $TESTFILE
	grep '^'"$SUBNAME"' '"$OBNAME" $LOAD
	exit 1
else
	echo Expected '"'$OBNAME'"' and got '"'$GOT'"' successfully.
fi

#
# Verify correct label behavior with a transmute
# directory and subdirectories
#

echo "$SUBNAME" > /proc/self/attr/current
rm -rf $TESTSUBDIR
su - $NOTROOT -c "mkdir $TESTSUBDIR"
grep `cat /proc/self/attr/current` $LOAD
echo Dir: `attr -q -S -g SMACK64 $TESTDIR 2> /dev/null` `ls -id $TESTDIR` `attr -q -S -g SMACK64TRANSMUTE $TESTDIR 2> /dev/null`
echo Dir: `attr -q -S -g SMACK64 $TESTSUBDIR 2> /dev/null` `ls -id $TESTSUBDIR` `attr -q -S -g SMACK64TRANSMUTE $TESTSUBDIR 2> /dev/null`
echo "$RUNAS" > /proc/self/attr/current
GOT=`attr -q -S -g SMACK64 $TESTSUBDIR`
if [ 'x'"$OBNAME" != 'x'"$GOT" ]
then
	echo Expected '"'$OBNAME'"' but got '"'$GOT'"'.
else
	echo Expected '"'$OBNAME'"' and got '"'$GOT'"' successfully.
fi

echo "$SUBNAME" > /proc/self/attr/current
rm -rf $TESTSUB2DIR
su - $NOTROOT -c "mkdir $TESTSUB2DIR"
grep `cat /proc/self/attr/current` $LOAD
echo Dir: `attr -q -S -g SMACK64 $TESTDIR 2> /dev/null` `ls -id $TESTDIR` `attr -q -S -g SMACK64TRANSMUTE $TESTDIR 2> /dev/null`
echo Dir: `attr -q -S -g SMACK64 $TESTSUBDIR 2> /dev/null` `ls -id $TESTSUBDIR` `attr -q -S -g SMACK64TRANSMUTE $TESTSUBDIR 2> /dev/null`
echo Dir: `attr -q -S -g SMACK64 $TESTSUB2DIR 2> /dev/null` `ls -id $TESTSUB2DIR` `attr -q -S -g SMACK64TRANSMUTE $TESTSUB2DIR 2> /dev/null`
echo "$RUNAS" > /proc/self/attr/current
GOT=`attr -q -S -g SMACK64 $TESTSUB2DIR`
if [ 'x'"$OBNAME" != 'x'"$GOT" ]
then
	echo Expected '"'$OBNAME'"' but got '"'$GOT'"'.
else
	echo Expected '"'$OBNAME'"' and got '"'$GOT'"' successfully.
fi

echo "$SUBNAME" > /proc/self/attr/current
rm -rf $TESTSUB3DIR
su - $NOTROOT -c "mkdir $TESTSUB3DIR"
grep `cat /proc/self/attr/current` $LOAD
echo Dir: `attr -q -S -g SMACK64 $TESTDIR 2> /dev/null` `ls -id $TESTDIR` `attr -q -S -g SMACK64TRANSMUTE $TESTDIR 2> /dev/null`
echo Dir: `attr -q -S -g SMACK64 $TESTSUBDIR 2> /dev/null` `ls -id $TESTSUBDIR` `attr -q -S -g SMACK64TRANSMUTE $TESTSUBDIR 2> /dev/null`
echo Dir: `attr -q -S -g SMACK64 $TESTSUB2DIR 2> /dev/null` `ls -id $TESTSUB2DIR` `attr -q -S -g SMACK64TRANSMUTE $TESTSUB2DIR 2> /dev/null`
echo Dir: `attr -q -S -g SMACK64 $TESTSUB3DIR 2> /dev/null` `ls -id $TESTSUB3DIR` `attr -q -S -g SMACK64TRANSMUTE $TESTSUB3DIR 2> /dev/null`
echo "$RUNAS" > /proc/self/attr/current
GOT=`attr -q -S -g SMACK64 $TESTSUB3DIR`
if [ 'x'"$OBNAME" != 'x'"$GOT" ]
then
	echo Expected '"'$OBNAME'"' but got '"'$GOT'"'.
else
	echo Expected '"'$OBNAME'"' and got '"'$GOT'"' successfully.
fi

#
# test SMACK64TRANSMUTE removal
#
echo test SMACK64TRANSMUTE removal

attr -S -g SMACK64TRANSMUTE $TESTSUB3DIR
rm -rf $TESTSUB3DIR
attr -S -r SMACK64TRANSMUTE $TESTSUB2DIR
su - $NOTROOT -c "mkdir $TESTSUB3DIR"
attr -S -g SMACK64TRANSMUTE $TESTSUB2DIR
attr -S -g SMACK64TRANSMUTE $TESTSUB3DIR

rm -rf $TESTDIR
#
# Restore old label rule.
#
if [ "x""$OLDRULE" != "x" ]
then
	RAWOLDMODE=`echo $OLDRULE | sed -e 's/.* //'`

	I=`echo $RAWOLDMODE | grep 'r'`
	if [ "x""$I" = "x" ]
	then
		OLDMODE="-"
	else
		OLDMODE="r"
	fi
	I=`echo $RAWOLDMODE | grep 'w'`
	if [ "x""$I" = "x" ]
	then
		OLDMODE="$OLDMODE""-"
	else
		OLDMODE="$OLDMODE""w"
	fi
	I=`echo $RAWOLDMODE | grep 'x'`
	if [ "x""$I" = "x" ]
	then
		OLDMODE="$OLDMODE""-"
	else
		OLDMODE="$OLDMODE""x"
	fi
	I=`echo $RAWOLDMODE | grep 'a'`
	if [ "x""$I" = "x" ]
	then
		OLDMODE="$OLDMODE""-"
	else
		OLDMODE="$OLDMODE""a"
	fi
	I=`echo $RAWOLDMODE | grep 't'`
	if [ "x""$I" = "x" ]
	then
		OLDMODE="$OLDMODE""-"
	else
		OLDMODE="$OLDMODE""t"
	fi

	echo -n "$SUBJECT"' '"$OBJECT"' '"$OLDMODE" > $LOAD
	# echo Rule reset to '"'"$SUBNAME"' '"$OBNAME"' '"$OLDMODE"'"'
else
	echo -n "$SUBJECT"' '"$OBJECT"' ''-----' > $LOAD
	# echo Rule reset to '"'"$SUBNAME"' '"$OBNAME"' '"-----"'"'
fi

echo "$RUNAS" > /proc/self/attr/current
rm -rf $TESTDIR

exit 0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.