--- 2.4-xfs/fs/xfs/linux/xfs_iops.c.acl Mon Oct 15 20:03:22 2001 +++ 2.4-xfs/fs/xfs/linux/xfs_iops.c Mon May 27 11:28:46 2002 @@ -74,10 +74,14 @@ struct inode *ip; vattr_t va; #ifdef CONFIG_FS_POSIX_ACL - struct acl pdacl; /* parent default ACL */ + struct acl *pdacl; /* parent default ACL */ #endif int have_default_acl; + ACL_ALLOC(pdacl); + if(!pdacl) + return -ENOMEM; + dvp = LINVFS_GET_VN_ADDRESS(dir); ASSERT(dvp); @@ -87,7 +91,7 @@ bzero(&va, sizeof(va)); va.va_mask = AT_TYPE|AT_MODE; va.va_type = tp; - have_default_acl = _ACL_GET_DEFAULT(dvp, &pdacl); + have_default_acl = _ACL_GET_DEFAULT(dvp, pdacl); if (!have_default_acl) { mode &= ~current->fs->umask; } @@ -107,6 +111,7 @@ va.va_type = IFTOVT(mode); if (va.va_type == VNON) { + ACL_FREE(pdacl); return -EINVAL; } VOP_CREATE(dvp, (char *)dentry->d_name.name, &va, 0, 0, &vp, @@ -123,6 +128,7 @@ ip = LINVFS_GET_IP(vp); if (!ip) { VN_RELE(vp); + ACL_FREE(pdacl); return -ENOMEM; } if (ISVDEV(tp)) @@ -135,10 +141,12 @@ } if (!error && have_default_acl) { - error = _ACL_INHERIT(vp, &va, &pdacl); + error = _ACL_INHERIT(vp, &va, pdacl); VMODIFY(vp); } + ACL_FREE(pdacl); + return -error; } --- 2.4-xfs/fs/xfs/linux/acl.h.acl Mon May 27 11:29:14 2002 +++ 2.4-xfs/fs/xfs/linux/acl.h Mon May 27 15:30:03 2002 @@ -59,7 +59,7 @@ * (USER_OBJ, GROUP_OBJ, MASK, & OTHER_OBJ) */ #define NACLBASE 4 -#define ACL_MAX_ENTRIES 25 /* Arbitrarily chosen number */ +#define ACL_MAX_ENTRIES 105 /* Arbitrarily chosen number */ /* * Data types required by POSIX P1003.1eD15 @@ -83,6 +83,42 @@ struct acl_entry acl_entry[ACL_MAX_ENTRIES]; }; +#ifdef XFS_ACL_DEBUG +static long acl_kmem = 0; + #define ACL_ALLOC(ptr) \ + do { \ + ptr = (struct acl *)kmalloc((size_t)sizeof(struct acl), GFP_KERNEL); \ + if (ptr == 0) { \ + printk(KERN_ERR "kmalloc returns 0 at %s:%d\n", \ + __FILE__, __LINE__); \ + } else { \ + acl_kmem += sizeof(struct acl); \ + printk(KERN_INFO "acl_alloc %d, kmem %ld\n", \ + (size_t)sizeof(struct acl), acl_kmem); \ + } \ + } while (0) + + #define ACL_FREE(ptr) \ + do { \ + kfree((ptr)); \ + acl_kmem -= sizeof(struct acl); \ + printk(KERN_INFO "acl_free %d, kmem %ld\n", \ + (size_t)sizeof(struct acl), acl_kmem); \ + } while (0) + +#else + #define ACL_ALLOC(ptr) \ + do { \ + ptr = (struct acl *)kmalloc((size_t) sizeof(struct acl), GFP_KERNEL); \ + } while (0) + + #define ACL_FREE(ptr) \ + do { \ + kfree((ptr)); \ + } while (0) + +#endif /* XFS_ACL_DEBUG */ + /* * Values for acl_get_entry */ --- 2.4-xfs/fs/xfs/xfs_acl.c.acl Mon Jul 9 14:16:12 2001 +++ 2.4-xfs/fs/xfs/xfs_acl.c Mon May 27 11:28:46 2002 @@ -45,27 +45,40 @@ int xfs_acl_iaccess( xfs_inode_t *ip, mode_t mode, cred_t *cr ) { - struct acl acl; + struct acl *pacl; + int rc = 0; + + ACL_ALLOC(pacl); + if(!pacl) + return ENOMEM; /* XFS return positive errors */ /* * If the file has no ACL return -1. */ - if (xfs_attr_fetch(ip, SGI_ACL_FILE, (char *)&acl, sizeof(struct acl))) - return -1; - xfs_acl_get_endian(&acl); + if (xfs_attr_fetch(ip, SGI_ACL_FILE, (char *)pacl, sizeof(struct acl))) { + rc = -1; + goto exit; + } + xfs_acl_get_endian(pacl); /* * If the file has an empty ACL return -1. */ - if (acl.acl_cnt == ACL_NOT_PRESENT) - return -1; + if (pacl->acl_cnt == ACL_NOT_PRESENT) { + rc = -1; + goto exit; + } /* * Synchronize ACL with mode bits */ - xfs_acl_sync_mode(ip->i_d.di_mode, &acl); + xfs_acl_sync_mode(ip->i_d.di_mode, pacl); - return xfs_acl_access(ip->i_d.di_uid, ip->i_d.di_gid, &acl, mode, cr); + rc = xfs_acl_access(ip->i_d.di_uid, ip->i_d.di_gid, pacl, mode, cr); + +exit: + ACL_FREE(pacl); + return rc; } /* @@ -315,23 +328,31 @@ xfs_acl_set_attr(vnode_t *vp, struct acl *aclp, int kind, int *error) { struct acl_entry *ace, *newace, *end; - struct acl newacl; + struct acl *pnewacl; int len = sizeof(struct acl); + ACL_ALLOC(pnewacl); + if(!pnewacl) { + printk("Not enough memory!\n"); + return; + } + /* do the endian conversion */ /* loop thru ACEs of ACL */ end = &aclp->acl_entry[0]+aclp->acl_cnt; - for (ace=&aclp->acl_entry[0],newace=&newacl.acl_entry[0]; ace < end; + for (ace=&aclp->acl_entry[0],newace=&(pnewacl->acl_entry[0]); ace < end; ace++,newace++) { INT_SET(newace->ae_tag, ARCH_CONVERT, ace->ae_tag); INT_SET(newace->ae_id, ARCH_CONVERT, ace->ae_id); INT_SET(newace->ae_perm, ARCH_CONVERT, ace->ae_perm); } - INT_SET(newacl.acl_cnt, ARCH_CONVERT, aclp->acl_cnt); + INT_SET(pnewacl->acl_cnt, ARCH_CONVERT, aclp->acl_cnt); VOP_ATTR_SET(vp, kind==ACL_ACCESS ? SGI_ACL_FILE: SGI_ACL_DEFAULT, - (char *)&newacl, len, ATTR_ROOT, sys_cred, *error); + (char *)pnewacl, len, ATTR_ROOT, sys_cred, *error); + + ACL_FREE(pnewacl); } STATIC int @@ -383,7 +404,7 @@ int xfs_acl_inherit(vnode_t *vp, vattr_t *vap, struct acl *pdaclp) { - struct acl cacl; + struct acl *pcacl; int error = 0; /* @@ -395,6 +416,11 @@ if (pdaclp == NULL || xfs_acl_invalid(pdaclp)) return (0); + ACL_ALLOC(pcacl); + if(!pcacl) { + return ENOMEM; + } + /* * Copy the default ACL of the containing directory to * the access ACL of the new file and use the mode that @@ -402,11 +428,11 @@ * the u::,g::[m::], and o:: entries. This is what makes * umask() "work" with ACL's. */ - memcpy(&cacl, pdaclp, sizeof(cacl)); - xfs_acl_filter_mode(vap->va_mode, &cacl); + memcpy(pcacl, pdaclp, sizeof(struct acl)); + xfs_acl_filter_mode(vap->va_mode, pcacl); /* set the mode to the acl */ - xfs_acl_setmode(vp, &cacl); + xfs_acl_setmode(vp, pcacl); /* * Set the default and access acl on the file. The mode is already @@ -420,9 +446,11 @@ xfs_acl_set_attr(vp, pdaclp, ACL_DEFAULT, &error); } if (!error) { - xfs_acl_set_attr(vp, &cacl, ACL_ACCESS, &error); + xfs_acl_set_attr(vp, pcacl, ACL_ACCESS, &error); } + ACL_FREE(pcacl); + return (error); } @@ -430,11 +458,16 @@ STATIC int xfs_acl_vget(vnode_t *vp, int kind, struct acl *acl) { - struct acl kacl; - int size = sizeof(kacl); + struct acl *pkacl; + int size = sizeof(struct acl); int error = 0; vattr_t va; + ACL_ALLOC(pkacl); + if(!pkacl) { + return ENOMEM; + } + #ifdef SERIOUS_DEBUG cmn_err(CE_NOTE, "xfs_acl_vget 0x%x %s 0x%x", vp, (kind == ACL_ACCESS) ? "ACCESS_ACL" : "DEFAULT_ACL", acl); #endif /* SERIOUS_DEBUG */ @@ -442,10 +475,10 @@ /* * Get the ACL if there is one... */ - memset(&kacl, 0, size); /* Make sure we don't copyout random stack */ - xfs_acl_get_attr(vp, &kacl, kind, &error); + memset(pkacl, 0, size); /* Make sure we don't copyout random stack */ + xfs_acl_get_attr(vp, pkacl, kind, &error); - if (!error && xfs_acl_invalid(&kacl)) { + if (!error && xfs_acl_invalid(pkacl)) { #ifdef SERIOUS_DEBUG cmn_err(CE_WARN, "Invalid acl fetched"); #endif /* SERIOUS_DEBUG */ @@ -466,13 +499,13 @@ * ACL, then the ACL is deemed NOT PRESENT. */ if (error) { - kacl.acl_cnt = ACL_NOT_PRESENT; + pkacl->acl_cnt = ACL_NOT_PRESENT; } else if (kind == ACL_ACCESS) { /* * Synchronize an Access ACL with the mode before * copying it out. */ - xfs_acl_sync_mode(va.va_mode, &kacl); + xfs_acl_sync_mode(va.va_mode, pkacl); } @@ -485,10 +518,13 @@ if (error == ENOATTR) error = 0; - if (!error && copyout((caddr_t)&kacl, (caddr_t)acl, + if (!error && copyout((caddr_t)pkacl, (caddr_t)acl, sizeof(struct acl))) { error = EFAULT; } + + ACL_FREE(pkacl); + return (error); } @@ -593,19 +629,33 @@ int xfs_acl_set(vnode_t *vp, struct acl *acl, struct acl *dacl) { - struct acl kacl; - struct acl kdacl; + struct acl *pkacl; + struct acl *pkdacl; vattr_t va; int error; if (!acl && !dacl) return (EINVAL); - if (acl && copy_from_user((caddr_t)&kacl, (caddr_t)acl, - sizeof (struct acl))) - return (EFAULT); - if (dacl && copy_from_user((caddr_t)&kdacl, (caddr_t)dacl, - sizeof (struct acl))) - return (EFAULT); + ACL_ALLOC(pkacl); + if(!pkacl) { + return ENOMEM; + } + ACL_ALLOC(pkdacl); + if(!pkdacl) { + ACL_FREE(pkacl); + return ENOMEM; + } + + if (acl && copy_from_user((caddr_t)pkacl, (caddr_t)acl, + sizeof (struct acl))) { + error = (EFAULT); + goto exit; + } + if (dacl && copy_from_user((caddr_t)pkdacl, (caddr_t)dacl, + sizeof (struct acl))) { + error = (EFAULT); + goto exit; + } VN_HOLD(vp); @@ -630,15 +680,20 @@ /* * Set the access ACL. */ - error = xfs_acl_vset(vp, &kacl); + error = xfs_acl_vset(vp, pkacl); if (!error && dacl) /* * Set the default ACL. */ - error = xfs_dacl_vset(vp, &kdacl); + error = xfs_dacl_vset(vp, pkdacl); } VN_RELE(vp); + +exit: + ACL_FREE(pkacl); + ACL_FREE(pkdacl); + return (error); }