svn commit: r308707 - stable/11/sys/ufs/ufs
Kirk McKusick
mckusick at FreeBSD.org
Wed Nov 16 01:03:43 UTC 2016
Author: mckusick
Date: Wed Nov 16 01:03:42 2016
New Revision: 308707
URL: https://svnweb.freebsd.org/changeset/base/308707
Log:
MFC r307978:
Bug 180894 reports that rm -rf on a directory causes kernel panic and reboot.
Return EINVAL rather than panic for low directory link count.
PR: 180894
Modified:
stable/11/sys/ufs/ufs/ufs_vnops.c
Directory Properties:
stable/11/ (props changed)
Modified: stable/11/sys/ufs/ufs/ufs_vnops.c
==============================================================================
--- stable/11/sys/ufs/ufs/ufs_vnops.c Wed Nov 16 00:21:18 2016 (r308706)
+++ stable/11/sys/ufs/ufs/ufs_vnops.c Wed Nov 16 01:03:42 2016 (r308707)
@@ -105,7 +105,7 @@ static vop_create_t ufs_create;
static vop_getattr_t ufs_getattr;
static vop_ioctl_t ufs_ioctl;
static vop_link_t ufs_link;
-static int ufs_makeinode(int mode, struct vnode *, struct vnode **, struct componentname *);
+static int ufs_makeinode(int mode, struct vnode *, struct vnode **, struct componentname *, const char *);
static vop_markatime_t ufs_markatime;
static vop_mkdir_t ufs_mkdir;
static vop_mknod_t ufs_mknod;
@@ -204,7 +204,7 @@ ufs_create(ap)
error =
ufs_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode),
- ap->a_dvp, ap->a_vpp, ap->a_cnp);
+ ap->a_dvp, ap->a_vpp, ap->a_cnp, "ufs_create");
if (error != 0)
return (error);
if ((ap->a_cnp->cn_flags & MAKEENTRY) != 0)
@@ -232,7 +232,7 @@ ufs_mknod(ap)
int error;
error = ufs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode),
- ap->a_dvp, vpp, ap->a_cnp);
+ ap->a_dvp, vpp, ap->a_cnp, "ufs_mknod");
if (error)
return (error);
ip = VTOI(*vpp);
@@ -942,6 +942,17 @@ out:
return (error);
}
+static void
+print_bad_link_count(const char *funcname, struct vnode *dvp)
+{
+ struct inode *dip;
+
+ dip = VTOI(dvp);
+ uprintf("%s: Bad link count %d on parent inode %d in file system %s\n",
+ funcname, dip->i_effnlink, dip->i_number,
+ dvp->v_mount->mnt_stat.f_mntonname);
+}
+
/*
* link vnode call
*/
@@ -964,9 +975,11 @@ ufs_link(ap)
if ((cnp->cn_flags & HASBUF) == 0)
panic("ufs_link: no name");
#endif
- if (VTOI(tdvp)->i_effnlink < 2)
- panic("ufs_link: Bad link count %d on parent",
- VTOI(tdvp)->i_effnlink);
+ if (VTOI(tdvp)->i_effnlink < 2) {
+ print_bad_link_count("ufs_link", tdvp);
+ error = EINVAL;
+ goto out;
+ }
ip = VTOI(vp);
if ((nlink_t)ip->i_nlink >= LINK_MAX) {
error = EMLINK;
@@ -1710,10 +1723,10 @@ ufs_do_posix1e_acl_inheritance_file(stru
* XXX: This should not happen, as EOPNOTSUPP above was
* supposed to free acl.
*/
- printf("ufs_makeinode: VOP_GETACL() but no "
- "VOP_SETACL()\n");
- /* panic("ufs_makeinode: VOP_GETACL() but no "
- "VOP_SETACL()"); */
+ printf("ufs_do_posix1e_acl_inheritance_file: VOP_GETACL() "
+ "but no VOP_SETACL()\n");
+ /* panic("ufs_do_posix1e_acl_inheritance_file: VOP_GETACL() "
+ "but no VOP_SETACL()"); */
break;
default:
@@ -1791,6 +1804,11 @@ ufs_mkdir(ap)
* but not have it entered in the parent directory. The entry is
* made later after writing "." and ".." entries.
*/
+ if (dp->i_effnlink < 2) {
+ print_bad_link_count("ufs_mkdir", dvp);
+ error = EINVAL;
+ goto out;
+ }
error = UFS_VALLOC(dvp, dmode, cnp->cn_cred, &tvp);
if (error)
goto out;
@@ -2021,13 +2039,12 @@ ufs_rmdir(ap)
* tries to remove a locally mounted on directory).
*/
error = 0;
- if (ip->i_effnlink < 2) {
+ if (dp->i_effnlink <= 2) {
+ if (dp->i_effnlink == 2)
+ print_bad_link_count("ufs_rmdir", dvp);
error = EINVAL;
goto out;
}
- if (dp->i_effnlink < 3)
- panic("ufs_dirrem: Bad link count %d on parent",
- dp->i_effnlink);
if (!ufs_dirempty(ip, dp->i_number, cnp->cn_cred)) {
error = ENOTEMPTY;
goto out;
@@ -2106,7 +2123,7 @@ ufs_symlink(ap)
int len, error;
error = ufs_makeinode(IFLNK | ap->a_vap->va_mode, ap->a_dvp,
- vpp, ap->a_cnp);
+ vpp, ap->a_cnp, "ufs_symlink");
if (error)
return (error);
vp = *vpp;
@@ -2558,11 +2575,12 @@ ufs_vinit(mntp, fifoops, vpp)
* Vnode dvp must be locked.
*/
static int
-ufs_makeinode(mode, dvp, vpp, cnp)
+ufs_makeinode(mode, dvp, vpp, cnp, callfunc)
int mode;
struct vnode *dvp;
struct vnode **vpp;
struct componentname *cnp;
+ const char *callfunc;
{
struct inode *ip, *pdir;
struct direct newdir;
@@ -2572,15 +2590,16 @@ ufs_makeinode(mode, dvp, vpp, cnp)
pdir = VTOI(dvp);
#ifdef INVARIANTS
if ((cnp->cn_flags & HASBUF) == 0)
- panic("ufs_makeinode: no name");
+ panic("%s: no name", callfunc);
#endif
*vpp = NULL;
if ((mode & IFMT) == 0)
mode |= IFREG;
- if (VTOI(dvp)->i_effnlink < 2)
- panic("ufs_makeinode: Bad link count %d on parent",
- VTOI(dvp)->i_effnlink);
+ if (pdir->i_effnlink < 2) {
+ print_bad_link_count(callfunc, dvp);
+ return (EINVAL);
+ }
error = UFS_VALLOC(dvp, mode, cnp->cn_cred, &tvp);
if (error)
return (error);
More information about the svn-src-all
mailing list