diff options
author | bde <bde@FreeBSD.org> | 1994-12-27 12:37:36 +0000 |
---|---|---|
committer | bde <bde@FreeBSD.org> | 1994-12-27 12:37:36 +0000 |
commit | 1587b568dd32b6f0f1d6cc5e282a606459d7ee2e (patch) | |
tree | adf9bcdb7a70ae862914612112ca8fbaee09e226 /sys/msdosfs | |
parent | 94497e0a34c7b774c88ebe2d120a83d82e6361f9 (diff) | |
download | FreeBSD-src-1587b568dd32b6f0f1d6cc5e282a606459d7ee2e.zip FreeBSD-src-1587b568dd32b6f0f1d6cc5e282a606459d7ee2e.tar.gz |
Fix panic for `cp -p' by root to an msdos file system. Improve handling
of attributes so that `cp -p' to an msdos file system can succeed under
favourable circumstances (no uid or gid changes and no nonzero flags
except SF_ARCHIVED).
msdosfs_vnops.c:
The in-core inode flags were confused with the on-disk inode flags, so
chflags() clobbered the lock flag and caused a panic.
denode.h, msdosfs_denode.c, msdosfs_vnops.c:
Support the msdosfs archive attibute (ATTR_ARCHIVE) by mapping it to
the complement of the SF_ARCHIVED flag and setting the ATTR_ARCHIVE
bit when a file's modification time is set (but not when a file's
permissions are set; this is the standard wrong DOS behaviour).
denode.h, msdosfs_denode.c:
Remove the DE_UPDAT() macro. It was only used once, and the corresponding
macro in ufs has already been removed.
denode.h:
Don't change the timestamp for directories in DE_TIMES() (be consistent
with deupdat()).
msdosfs_vnops.c:
Handle chown() better: return EPERM instead of EINVAL if there are
insufficient permissions; otherwise, allow null changes.
Diffstat (limited to 'sys/msdosfs')
-rw-r--r-- | sys/msdosfs/denode.h | 18 | ||||
-rw-r--r-- | sys/msdosfs/msdosfs_denode.c | 12 | ||||
-rw-r--r-- | sys/msdosfs/msdosfs_vnops.c | 56 |
3 files changed, 57 insertions, 29 deletions
diff --git a/sys/msdosfs/denode.h b/sys/msdosfs/denode.h index dce8fd6..a45994b 100644 --- a/sys/msdosfs/denode.h +++ b/sys/msdosfs/denode.h @@ -1,4 +1,4 @@ -/* $Id: denode.h,v 1.1 1994/09/19 15:41:38 dfr Exp $ */ +/* $Id: denode.h,v 1.2 1994/12/12 12:35:40 bde Exp $ */ /* $NetBSD: denode.h,v 1.8 1994/08/21 18:43:49 ws Exp $ */ /*- @@ -199,16 +199,16 @@ struct denode { #define VTODE(vp) ((struct denode *)(vp)->v_data) #define DETOV(de) ((de)->de_vnode) -#define DE_UPDAT(dep, t, waitfor) \ - if ((dep)->de_flag & (DE_MODIFIED | DE_UPDATE)) \ - (void) deupdat((dep), (t), (waitfor)); - #define DE_TIMES(dep, t) \ if ((dep)->de_flag & DE_UPDATE) { \ - struct timespec DE_TIMES_ts; \ - (dep)->de_flag |= DE_MODIFIED; \ - TIMEVAL_TO_TIMESPEC((t), &DE_TIMES_ts); \ - unix2dostime(&DE_TIMES_ts, &(dep)->de_Date, &(dep)->de_Time); \ + if (!((dep)->de_Attributes & ATTR_DIRECTORY)) { \ + struct timespec DE_TIMES_ts; \ + (dep)->de_flag |= DE_MODIFIED; \ + TIMEVAL_TO_TIMESPEC((t), &DE_TIMES_ts); \ + unix2dostime(&DE_TIMES_ts, &(dep)->de_Date, \ + &(dep)->de_Time); \ + (dep)->de_Attributes |= ATTR_ARCHIVE; \ + } \ (dep)->de_flag &= ~DE_UPDATE; \ } diff --git a/sys/msdosfs/msdosfs_denode.c b/sys/msdosfs/msdosfs_denode.c index b9720c0..c20b7e5 100644 --- a/sys/msdosfs/msdosfs_denode.c +++ b/sys/msdosfs/msdosfs_denode.c @@ -1,4 +1,4 @@ -/* $Id: msdosfs_denode.c,v 1.4 1994/10/10 07:57:32 phk Exp $ */ +/* $Id: msdosfs_denode.c,v 1.5 1994/12/12 12:35:43 bde Exp $ */ /* $NetBSD: msdosfs_denode.c,v 1.9 1994/08/21 18:44:00 ws Exp $ */ /*- @@ -351,8 +351,10 @@ deupdat(dep, tp, waitfor) * If the mtime is to be updated, put the passed in time into the * directory entry. */ - if (dep->de_flag & DE_UPDATE) + if (dep->de_flag & DE_UPDATE) { + dep->de_Attributes |= ATTR_ARCHIVE; unix2dostime(tp, &dep->de_Date, &dep->de_Time); + } /* * The mtime is now up to date. The denode will be unmodifed soon. @@ -688,8 +690,10 @@ msdosfs_inactive(ap) dep->de_flag |= DE_UPDATE; dep->de_Name[0] = SLOT_DELETED; } - TIMEVAL_TO_TIMESPEC(&time, &ts); - DE_UPDAT(dep, &ts, 0); + if (dep->de_flag & (DE_MODIFIED | DE_UPDATE)) { + TIMEVAL_TO_TIMESPEC(&time, &ts); + deupdat(dep, &ts, 0); + } VOP_UNLOCK(vp); dep->de_flag = 0; diff --git a/sys/msdosfs/msdosfs_vnops.c b/sys/msdosfs/msdosfs_vnops.c index 35c96f5..1948062 100644 --- a/sys/msdosfs/msdosfs_vnops.c +++ b/sys/msdosfs/msdosfs_vnops.c @@ -1,4 +1,4 @@ -/* $Id: msdosfs_vnops.c,v 1.9 1994/11/29 23:39:15 ache Exp $ */ +/* $Id: msdosfs_vnops.c,v 1.10 1994/12/12 12:35:50 bde Exp $ */ /* $NetBSD: msdosfs_vnops.c,v 1.20 1994/08/21 18:44:13 ws Exp $ */ /*- @@ -129,7 +129,8 @@ msdosfs_create(ap) TIMEVAL_TO_TIMESPEC(&time, &ts); unix2dostime(&ts, &ndirent.de_Date, &ndirent.de_Time); unix2dosfn((u_char *)cnp->cn_nameptr, ndirent.de_Name, cnp->cn_namelen); - ndirent.de_Attributes = (ap->a_vap->va_mode & VWRITE) ? 0 : ATTR_READONLY; + ndirent.de_Attributes = (ap->a_vap->va_mode & VWRITE) + ? ATTR_ARCHIVE : ATTR_ARCHIVE | ATTR_READONLY; ndirent.de_StartCluster = 0; ndirent.de_FileSize = 0; ndirent.de_dev = pdep->de_dev; @@ -329,7 +330,7 @@ msdosfs_getattr(ap) #endif #endif vap->va_ctime = vap->va_atime; - vap->va_flags = dep->de_flag; + vap->va_flags = (dep->de_Attributes & ATTR_ARCHIVE) ? 0 : SF_ARCHIVED; vap->va_gen = 0; vap->va_blocksize = dep->de_pmp->pm_bpcluster; vap->va_bytes = (dep->de_FileSize + dep->de_pmp->pm_crbomask) & @@ -363,21 +364,28 @@ msdosfs_setattr(ap) (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) || (vap->va_bytes != VNOVAL) || - (vap->va_gen != VNOVAL) || - (vap->va_uid != VNOVAL) || - (vap->va_gid != VNOVAL)) { + (vap->va_gen != VNOVAL)) { #ifdef MSDOSFS_DEBUG printf("msdosfs_setattr(): returning EINVAL\n"); printf(" va_type %d, va_nlink %x, va_fsid %x, va_fileid %x\n", vap->va_type, vap->va_nlink, vap->va_fsid, vap->va_fileid); printf(" va_blocksize %x, va_rdev %x, va_bytes %x, va_gen %x\n", vap->va_blocksize, vap->va_rdev, vap->va_bytes, vap->va_gen); - printf(" va_uid %x, va_gid %x\n", - vap->va_uid, vap->va_gid); #endif return EINVAL; } + if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (uid_t)VNOVAL) { + if ((cred->cr_uid != dep->de_pmp->pm_uid || + vap->va_uid != dep->de_pmp->pm_uid || + (vap->va_gid != dep->de_pmp->pm_gid && + !groupmember(vap->va_gid, cred))) && + (error = suser(cred, &ap->a_p->p_acflag))) + return error; + if (vap->va_uid != dep->de_pmp->pm_uid || + vap->va_gid != dep->de_pmp->pm_gid) + return EINVAL; + } if (vap->va_size != VNOVAL) { if (ap->a_vp->v_type == VDIR) return EISDIR; @@ -393,7 +401,7 @@ msdosfs_setattr(ap) } /* - * DOS files only have the ability to have thier writability + * DOS files only have the ability to have their writability * attribute set, so we use the owner write bit to set the readonly * attribute. */ @@ -407,15 +415,31 @@ msdosfs_setattr(ap) } if (vap->va_flags != VNOVAL) { - error = suser(cred, &ap->a_p->p_acflag); - if (error) + if (cred->cr_uid != dep->de_pmp->pm_uid && + (error = suser(cred, &ap->a_p->p_acflag))) return error; - if (cred->cr_uid == 0) - dep->de_flag = vap->va_flags; - else { - dep->de_flag &= 0xffff0000; - dep->de_flag |= (vap->va_flags & 0xffff); + /* + * We are very inconsistent about handling unsupported + * attributes. We ignored the the access time and the + * read and execute bits. We were strict for the other + * attributes. + * + * Here we are strict, stricter than ufs in not allowing + * users to attempt to set SF_SETTABLE bits or anyone to + * set unsupported bits. However, we ignore attempts to + * set ATTR_ARCHIVE for directories `cp -pr' from a more + * sensible file system attempts it a lot. + */ + if (cred->cr_uid != 0) { + if (vap->va_flags & SF_SETTABLE) + return EPERM; } + if (vap->va_flags & ~SF_ARCHIVED) + return EINVAL; + if (vap->va_flags & SF_ARCHIVED) + dep->de_Attributes &= ~ATTR_ARCHIVE; + else if (!(dep->de_Attributes & ATTR_DIRECTORY)) + dep->de_Attributes |= ATTR_ARCHIVE; dep->de_flag |= DE_MODIFIED; } return error; |