|
Neohapsis is currently accepting applications for employment. For more information, please visit our website www.neohapsis.com or email hr@neohapsis.com |
setuid logging
From: Matt Provost (mprovost
termcap.net)
Date: Tue Jun 01 2004 - 23:47:27 CDT
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Here's a patch to enable setuid logging in -current. I've tested it on
i386/GENERIC which is the only platform that I have. Skipping the find
that /etc/security runs every night really cuts down the amount of time
that it takes to run. To enable it, `sysctl fs.logsetuid=1`. It's also
only been tested on FFS but I don't see why it shouldn't work on other
filesystems (unless there is a problem with the inode numbers?).
The chmod system call will now output lines like:
/bsd: Setuid bit set by uid 1000 on file /tmp/a in filesystem mounted on /
fchmod doesn't have any idea what the filename is, so for now it just
prints out the inode number, like:
/bsd: Setuid bit set by uid 0 on inode 101240 in filesystem mounted
nosuid on /var
So it would be possible to do a `find /var -inum 101240` to locate the
file. It might be possible to try and find the vnode in the namei cache
but I haven't done that yet.
I also put in checks (as you can see above) for filesystems mounted
nosuid and noexec. I didn't add code for setgid files - not sure if it's
a good idea and hoping to get some feedback.
While working on this it occurred to me that perhaps the best thing to
do on a filesystem mounted nosuid would be to have chmod return the
equivalent of EROFS. Stretching that example, should chmod return an
error if you set the execute bit on a file in a filesystem mounted
noexec? I'm not sure how many things that would break. It does seem
strange to allow someone to set permissions on files that are then
overridden by mount options, but that could come back later when the
filesystem is mounted exec/suid.
Comments?
Matt
Index: /usr/src/sys/kern/vfs_syscalls.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_syscalls.c,v
retrieving revision 1.111
diff -c -r1.111 vfs_syscalls.c
*** /usr/src/sys/kern/vfs_syscalls.c 14 May 2004 04:00:33 -0000 1.111
--- /usr/src/sys/kern/vfs_syscalls.c 1 Jun 2004 23:45:52 -0000
***************
*** 58,64 ****
--- 58,69 ----
#include <uvm/uvm_extern.h>
#include <sys/sysctl.h>
+ #include <sys/syslog.h>
+ #include <ufs/ufs/quota.h>
+ #include <ufs/ufs/inode.h>
+
extern int suid_clear;
+ extern int log_setuid;
int usermount = 0; /* sysctl: by default, users may not mount */
static int change_dir(struct nameidata *, struct proc *);
***************
*** 1896,1906 ****
struct vattr vattr;
int error;
struct nameidata nd;
if (SCARG(uap, mode) & ~(S_IFMT | ALLPERMS))
return (EINVAL);
! NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
if ((error = namei(&nd)) != 0)
return (error);
vp = nd.ni_vp;
--- 1901,1915 ----
struct vattr vattr;
int error;
struct nameidata nd;
+ struct statfs *mntbuf;
if (SCARG(uap, mode) & ~(S_IFMT | ALLPERMS))
return (EINVAL);
! /* path = pool_get(&namei_pool, PR_WAITOK); */
!
! NDINIT(&nd, LOOKUP, FOLLOW | SAVENAME, UIO_USERSPACE, SCARG(uap, path), p);
!
if ((error = namei(&nd)) != 0)
return (error);
vp = nd.ni_vp;
***************
*** 1914,1919 ****
--- 1923,1961 ----
error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
}
vput(vp);
+
+ /*
+ * log if setuid bit is set
+ */
+ if ((SCARG(uap, mode) & S_ISUID)
+ && !error
+ && log_setuid) {
+ /* get the filesystem that the file is in*/
+ mntbuf = &vp->v_mount->mnt_stat;
+
+ /* check if the fs is mounted 'nosuid' */
+ if (vp->v_mount->mnt_flag & MNT_NOSUID) {
+ /* send notice to syslog */
+ log(LOG_NOTICE, "Setuid bit set by uid %u on file %s in filesystem mounted nosuid on %s\n",
+ p->p_cred->p_ruid, nd.ni_cnd.cn_pnbuf, mntbuf->f_mntonname);
+ /* check if the fs is mounted 'noexec' */
+ } else if (vp->v_mount->mnt_flag & MNT_NOEXEC) {
+ /* send notice to syslog */
+ log(LOG_NOTICE, "Setuid bit set by uid %u on file %s in filesystem mounted noexec on %s\n",
+ p->p_cred->p_ruid, nd.ni_cnd.cn_pnbuf, mntbuf->f_mntonname);
+ /* check for both ? */
+ /* else fs is mounted to allow setuid execution */
+ } else {
+ /* send notice to syslog */
+ log(LOG_NOTICE, "Setuid bit set by uid %u on file %s in filesystem mounted on %s\n",
+ p->p_cred->p_ruid, nd.ni_cnd.cn_pnbuf, mntbuf->f_mntonname);
+ }
+ } /* setuid */
+
+ /* we have to free the buffer since we specified SAVENAME in NDINIT */
+ /* FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI); */
+ pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
+
return (error);
}
***************
*** 1933,1940 ****
--- 1975,1984 ----
} */ *uap = v;
struct vattr vattr;
struct vnode *vp;
+ struct inode *ip;
struct file *fp;
int error;
+ struct statfs *mntbuf;
if (SCARG(uap, mode) & ~(S_IFMT | ALLPERMS))
return (EINVAL);
***************
*** 1953,1958 ****
--- 1997,2032 ----
}
VOP_UNLOCK(vp, 0, p);
FRELE(fp);
+
+ /*
+ * log if setuid bit is set
+ */
+ if ((SCARG(uap, mode) & S_ISUID)
+ && !error
+ && log_setuid) {
+ /* get the filesystem that the file is in */
+ mntbuf = &vp->v_mount->mnt_stat;
+
+ /* get the file's inode */
+ /* since we only have an fd, we can't get the filename so just log the inode number */
+ ip = VTOI(vp);
+
+ /* check if the fs is mounted 'nosuid' */
+ if (vp->v_mount->mnt_flag & MNT_NOSUID) {
+ /* send notice to syslog */
+ log(LOG_NOTICE, "Setuid bit set by uid %u on inode %u in filesystem mounted nosuid on %s\n",
+ p->p_cred->p_ruid, ip->i_number, mntbuf->f_mntonname);
+ } else if (vp->v_mount->mnt_flag & MNT_NOEXEC) {
+ /* send notice to syslog */
+ log(LOG_NOTICE, "Setuid bit set by uid %u on inode %u in filesystem mounted noexec on %s\n",
+ p->p_cred->p_ruid, ip->i_number, mntbuf->f_mntonname);
+ } else {
+ /* send notice to syslog */
+ log(LOG_NOTICE, "Setuid bit set by uid %u on inode %u in filesystem mounted on %s\n",
+ p->p_cred->p_ruid, ip->i_number, mntbuf->f_mntonname);
+ }
+ } /* setuid */
+
return (error);
}
Index: /usr/src/sys/kern/vfs_subr.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_subr.c,v
retrieving revision 1.100
diff -c -r1.100 vfs_subr.c
*** /usr/src/sys/kern/vfs_subr.c 27 May 2004 20:48:46 -0000 1.100
--- /usr/src/sys/kern/vfs_subr.c 1 Jun 2004 19:08:09 -0000
***************
*** 77,82 ****
--- 77,83 ----
int doforce = 1; /* 1 => permit forcible unmounting */
int prtactive = 0; /* 1 => print out reclaim of active vnodes */
int suid_clear = 1; /* 1 => clear SUID / SGID on owner change */
+ int log_setuid = 0; /* 1 => log file setuid changes */
/*
* Insq/Remq for the vnode usage lists.
***************
*** 1910,1919 ****
--- 1911,1932 ----
{
sysctlfn *fn;
+ int error, ctlval;
+
switch (name[0]) {
case FS_POSIX:
fn = fs_posix_sysctl;
break;
+ case FS_LOGSETUID:
+ ctlval = log_setuid;
+ if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &ctlval))
+ || newp == NULL)
+ return (error);
+ if (ctlval != 1 && ctlval != 0)
+ return (EINVAL);
+ /* return(sysctl_int(oldp, oldlenp, newp, newlen, &log_setuid));*/
+ log_setuid = ctlval;
+ return (0);
default:
return (EOPNOTSUPP);
}
Index: /usr/src/sys/sys/sysctl.h
===================================================================
RCS file: /cvs/src/sys/sys/sysctl.h,v
retrieving revision 1.77
diff -c -r1.77 sysctl.h
*** /usr/src/sys/sys/sysctl.h 19 Apr 2004 22:52:33 -0000 1.77
--- /usr/src/sys/sys/sysctl.h 13 May 2004 01:58:04 -0000
***************
*** 482,492 ****
* CTL_FS identifiers
*/
#define FS_POSIX 1 /* POSIX flags */
! #define FS_MAXID 2
#define CTL_FS_NAMES { \
{ 0, 0 }, \
{ "posix", CTLTYPE_NODE }, \
}
/*
--- 482,494 ----
* CTL_FS identifiers
*/
#define FS_POSIX 1 /* POSIX flags */
! #define FS_LOGSETUID 2 /* log setuid changes */
! #define FS_MAXID 3
#define CTL_FS_NAMES { \
{ 0, 0 }, \
{ "posix", CTLTYPE_NODE }, \
+ { "logsetuid", CTLTYPE_INT }, \
}
/*
Index: /usr/src/sbin/sysctl/sysctl.8
===================================================================
RCS file: /cvs/src/sbin/sysctl/sysctl.8,v
retrieving revision 1.122
diff -c -r1.122 sysctl.8
*** /usr/src/sbin/sysctl/sysctl.8 7 May 2004 21:58:14 -0000 1.122
--- /usr/src/sbin/sysctl/sysctl.8 2 Jun 2004 00:28:06 -0000
***************
*** 202,207 ****
--- 202,208 ----
.It vm.maxslp integer no
.It vm.uspace integer no
.It fs.posix.setuid integer yes
+ .It fs.logsetuid integer yes
.It net.inet.ip.forwarding integer yes
.It net.inet.ip.redirect integer yes
.It net.inet.ip.ttl integer yes
Index: /usr/src/sbin/sysctl/sysctl.c
===================================================================
RCS file: /cvs/src/sbin/sysctl/sysctl.c,v
retrieving revision 1.113
diff -c -r1.113 sysctl.c
*** /usr/src/sbin/sysctl/sysctl.c 15 Apr 2004 00:23:17 -0000 1.113
--- /usr/src/sbin/sysctl/sysctl.c 14 May 2004 18:59:06 -0000
***************
*** 605,614 ****
break;
case CTL_FS:
! len = sysctl_fs(string, &bufp, mib, flags, &type);
! if (len >= 0)
break;
! return;
case CTL_VFS:
if (mib[1])
--- 605,618 ----
break;
case CTL_FS:
! if (mib[1] == FS_POSIX) {
! len = sysctl_fs(string, &bufp, mib, flags, &type);
! if (len >= 0)
! break;
! return;
! } else {
break;
! }
case CTL_VFS:
if (mib[1])
Index: /usr/src/etc/security
===================================================================
RCS file: /cvs/src/etc/security,v
retrieving revision 1.66
diff -c -r1.66 security
*** /usr/src/etc/security 28 Dec 2003 19:51:31 -0000 1.66
--- /usr/src/etc/security 28 May 2004 23:35:37 -0000
***************
*** 457,530 ****
# Display any changes in setuid/setgid files and devices.
pending="\nChecking setuid/setgid files and devices:\n"
- (find / \( ! -fstype local -o -fstype fdesc -o -fstype kernfs \
- -o -fstype procfs \) -a -prune -o \
- -type f -a \( -perm -u+s -o -perm -g+s \) -print0 -o \
- ! -type d -a ! -type f -a ! -type l -a ! -type s -a ! -type p \
- -print0 | xargs -0 ls -ldgT | sort +9 > $LIST) 2> $OUTPUT
-
- # Display any errors that occurred during system file walk.
- if [ -s $OUTPUT ] ; then
- echo "${pending}Setuid/device find errors:"
- pending=
- cat $OUTPUT
- echo ""
- fi
! # Display any changes in the setuid/setgid file list.
! FIELDS1=1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,0
! FIELDS2=2.1,2.2,2.3,2.4,2.5,2.6,2.7,2.8,2.9,0
! egrep -av '^[bc]' $LIST | join -o $FIELDS2 -110 -210 -v2 /dev/null - > $TMP1
! if [ -s $TMP1 ] ; then
! # Check to make sure uudecode isn't setuid.
! if grep -aw uudecode $TMP1 > /dev/null ; then
! echo "${pending}\nUudecode is setuid."
pending=
fi
! CUR=/var/backups/setuid.current
! BACK=/var/backups/setuid.backup
!
! if [ -s $CUR ] ; then
! if cmp -s $CUR $TMP1 ; then
! :
! else
! > $TMP2
! join -o $FIELDS2 -110 -210 -v2 $CUR $TMP1 > $OUTPUT
! if [ -s $OUTPUT ] ; then
! echo "${pending}Setuid additions:"
! pending=
! tee -a $TMP2 < $OUTPUT | column -t
! echo ""
! fi
!
! join -o $FIELDS1 -110 -210 -v1 $CUR $TMP1 > $OUTPUT
! if [ -s $OUTPUT ] ; then
! echo "${pending}Setuid deletions:"
! pending=
! tee -a $TMP2 < $OUTPUT | column -t
! echo ""
! fi
! sort +9 $TMP2 $CUR $TMP1 | \
! sed -e 's/[ ][ ]*/ /g' | uniq -u > $OUTPUT
! if [ -s $OUTPUT ] ; then
! echo "${pending}Setuid changes:"
! pending=
! column -t $OUTPUT
! echo ""
fi
!
! cp $CUR $BACK
cp $TMP1 $CUR
fi
- else
- echo "${pending}Setuid additions:"
- pending=
- column -t $TMP1
- echo ""
- cp $TMP1 $CUR
fi
fi
# Check for block and character disk devices that are readable or writeable
--- 457,535 ----
# Display any changes in setuid/setgid files and devices.
pending="\nChecking setuid/setgid files and devices:\n"
! # First check to see if we are logging changes and can avoid a find
! if [ `/usr/sbin/sysctl fs.logsetuid` = "fs.logsetuid=1" ] ; then
! echo "\nSetuid/setgid logging enabled, skipping file check\n"
! else
! (find /\( ! -fstype local -o -fstype fdesc -o -fstype kernfs \
! -o -fstype procfs \) -a -prune -o \
! -type f -a \( -perm -u+s -o -perm -g+s \) -print0 -o \
! ! -type d -a ! -type f -a ! -type l -a ! -type s -a ! -type p \
! -print0 | xargs -0 ls -ldgT | sort +9 > $LIST) 2> $OUTPUT
!
! # Display any errors that occurred during system file walk.
! if [ -s $OUTPUT ] ; then
! echo "${pending}Setuid/device find errors:"
pending=
+ cat $OUTPUT
+ echo ""
fi
! # Display any changes in the setuid/setgid file list.
! FIELDS1=1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,0
! FIELDS2=2.1,2.2,2.3,2.4,2.5,2.6,2.7,2.8,2.9,0
! egrep -av '^[bc]' $LIST | join -o $FIELDS2 -110 -210 -v2 /dev/null - > $TMP1
! if [ -s $TMP1 ] ; then
! CUR=/var/backups/setuid.current
! BACK=/var/backups/setuid.backup
!
! if [ -s $CUR ] ; then
! if cmp -s $CUR $TMP1 ; then
! :
! else
! > $TMP2
! join -o $FIELDS2 -110 -210 -v2 $CUR $TMP1 > $OUTPUT
! if [ -s $OUTPUT ] ; then
! echo "${pending}Setuid additions:"
! pending=
! tee -a $TMP2 < $OUTPUT | column -t
! echo ""
! fi
!
! join -o $FIELDS1 -110 -210 -v1 $CUR $TMP1 > $OUTPUT
! if [ -s $OUTPUT ] ; then
! echo "${pending}Setuid deletions:"
! pending=
! tee -a $TMP2 < $OUTPUT | column -t
! echo ""
! fi
!
! sort +9 $TMP2 $CUR $TMP1 | \
! sed -e 's/[ ][ ]*/ /g' | uniq -u > $OUTPUT
! if [ -s $OUTPUT ] ; then
! echo "${pending}Setuid changes:"
! pending=
! column -t $OUTPUT
! echo ""
! fi
! cp $CUR $BACK
! cp $TMP1 $CUR
fi
! else
! echo "${pending}Setuid additions:"
! pending=
! column -t $TMP1
! echo ""
cp $TMP1 $CUR
fi
fi
+ fi
+ # Check to make sure uudecode isn't setuid.
+ if grep -aw uudecode $TMP1 > /dev/null ; then
+ echo "${pending}\nUudecode is setuid."
+ pending=
fi
# Check for block and character disk devices that are readable or writeable
Index: /usr/src/lib/libc/gen/sysctl.3
===================================================================
RCS file: /cvs/src/lib/libc/gen/sysctl.3,v
retrieving revision 1.138
diff -c -r1.138 sysctl.3
*** /usr/src/lib/libc/gen/sysctl.3 20 Apr 2004 06:41:47 -0000 1.138
--- /usr/src/lib/libc/gen/sysctl.3 2 Jun 2004 04:02:08 -0000
***************
*** 248,253 ****
--- 248,254 ----
.Bl -column "Second level nameXXXXXX" integerXXX -offset indent
.It Sy Second level name Type Changeable
.It Dv FS_POSIX_SETUID No " integer yes"
+ .It Dv FS_LOGSETUID No " integer yes"
.El
.Bl -tag -width "123456"
.It Dv FS_POSIX_SETUID
***************
*** 260,265 ****
--- 261,274 ----
As detailed in
.Xr securelevel 7 ,
this variable may not be changed if the securelevel is \*(Gt 0.
+ .It Dv FS_LOGSETUID
+ When this variable is set, adding the
+ .Va S_ISUID
+ bit to a file's permissions will be logged to syslog with the
+ .Va LOG_KERN
+ facility and
+ .Va LOG_INFO
+ level.
.El
.Ss CTL_HW
The string and integer information available for the
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]