Subject: Re: symlink complaints in /etc/security
To: Perry E. Metzger <perry@piermont.com>
From: Luke Mewburn <lukem@NetBSD.org>
List: tech-security
Date: 12/08/2003 14:15:14
--63tCqOYFH7xKgZE5
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
On Sun, Dec 07, 2003 at 09:16:28PM -0500, Perry E. Metzger wrote:
| > since it doesn't involve adding more special cases to mtree,
|
| Well, it does require that we rig mtree to handle this, or somehow
| build a script that does it for mtree....
|
| So how do we do it?
As I mentioned, using awk on the output of "mtree -C -K all" may be
sufficient, although it starts to get slightly messy.
Alternatively, we could implement mtree -M (? - merge) to allow
entries to be replaced with ones of a different type.
In /etc/security we'd then do something like:
cat $special_files | mtree -C -K all -M > ${SECUREDIR}/specials
and use ${SECUREDIR}/specials appropriately.
Currently spec.c::replacenode() in mtree forbids this (and that
is a sane default to retain); -M could relax that check.
The special case we need to consider is if "type==dir && child!=NULL".
For example, as special has
./etc/mail type=dir mode=0755
./etc/mail/aliases type=file mode=0644
./etc/mail/helpfile type=file mode=0444
if you replace /etc/mail with a symlink to /var/chroot/mail and add
the following to special.local
./etc/mail type=link link=/var/chroot/mail
./var type=dir mode=0755
./var/chroot type=dir mode=0755
./var/chroot/mail type=dir mode=0755
./var/chroot/mail/etc type=dir mode=0755
./var/chroot/mail/aliases type=file mode=0644
./var/chroot/mail/helpfile type=file mode=0644
the you don't want ./etc/mail/{aliases,helpfile} in the final
specfile.
Here's a proof of concept diff to mtree. Care to try it out on your
system with special.local whacked appropriately (and _without_ mtree -L)?
Cheers,
Luke.
--63tCqOYFH7xKgZE5
Content-Type: text/plain; charset=us-ascii
Content-Description: mtree-M.diff
Content-Disposition: attachment; filename=difz
? difz
Index: extern.h
===================================================================
RCS file: /cvsroot/src/usr.sbin/mtree/extern.h,v
retrieving revision 1.28
diff -p -p -u -r1.28 extern.h
--- extern.h 27 Oct 2003 00:12:44 -0000 1.28
+++ extern.h 8 Dec 2003 03:12:35 -0000
@@ -70,7 +70,7 @@ const char *rlink(const char *);
int verify(void);
extern int dflag, eflag, iflag, lflag, mflag, rflag, sflag, tflag, uflag;
-extern int Wflag;
+extern int Mflag, Wflag;
extern size_t mtree_lineno;
extern u_int32_t crc_total;
extern int ftsoptions, keys;
Index: mtree.c
===================================================================
RCS file: /cvsroot/src/usr.sbin/mtree/mtree.c,v
retrieving revision 1.30
diff -p -p -u -r1.30 mtree.c
--- mtree.c 7 Aug 2003 11:25:36 -0000 1.30
+++ mtree.c 8 Dec 2003 03:12:36 -0000
@@ -73,7 +73,7 @@ main(int argc, char **argv)
dir = NULL;
init_excludes();
- while ((ch = getopt(argc, argv, "cCdDeE:f:I:ik:K:lLmN:p:PrR:s:tuUWxX:"))
+ while ((ch = getopt(argc, argv, "cCdDeE:f:I:ik:K:lLmMN:p:PrR:s:tuUWxX:"))
!= -1) {
switch((char)ch) {
case 'c':
@@ -124,6 +124,9 @@ main(int argc, char **argv)
break;
case 'm':
mflag = 1;
+ break;
+ case 'M':
+ Mflag = 1;
break;
case 'N':
if (! setup_getid(optarg))
Index: spec.c
===================================================================
RCS file: /cvsroot/src/usr.sbin/mtree/spec.c,v
retrieving revision 1.53
diff -p -p -u -r1.53 spec.c
--- spec.c 17 Nov 2003 00:02:33 -0000 1.53
+++ spec.c 8 Dec 2003 03:12:36 -0000
@@ -92,6 +92,7 @@ __RCSID("$NetBSD: spec.c,v 1.53 2003/11/
#include "pack_dev.h"
size_t mtree_lineno; /* Current spec line number */
+int Mflag; /* Merge duplicate entries */
int Wflag; /* Don't "whack" permissions */
static dev_t parsedev(char *);
@@ -407,11 +408,24 @@ static void
replacenode(NODE *cur, NODE *new)
{
- if (cur->type != new->type)
- mtree_err("existing entry for `%s', type `%s' does not match type `%s'",
- cur->name, nodetype(cur->type), nodetype(new->type));
#define REPLACE(x) cur->x = new->x
#define REPLACESTR(x) if (cur->x) free(cur->x); cur->x = new->x
+ if (cur->type != new->type) {
+ if (Mflag) {
+ /*
+ * merge entries with different types; we
+ * don't want children retained in this case.
+ */
+ REPLACE(type);
+ cur->child = NULL;
+ } else {
+ mtree_err(
+ "existing entry for `%s', type `%s'"
+ " does not match type `%s'",
+ cur->name, nodetype(cur->type),
+ nodetype(new->type));
+ }
+ }
REPLACE(st_size);
REPLACE(st_mtimespec);
--63tCqOYFH7xKgZE5--