@@ -378,10 +378,111 @@ nfsd4_decode_security_label(struct nfsd4_compoundargs *argp,
378378 return nfs_ok ;
379379}
380380
381+ #ifdef CONFIG_NFSD_V4_POSIX_ACLS
382+
383+ static short nfsd4_posixacetag4_to_tag (posixacetag4 tag )
384+ {
385+ switch (tag ) {
386+ case POSIXACE4_TAG_USER_OBJ : return ACL_USER_OBJ ;
387+ case POSIXACE4_TAG_GROUP_OBJ : return ACL_GROUP_OBJ ;
388+ case POSIXACE4_TAG_USER : return ACL_USER ;
389+ case POSIXACE4_TAG_GROUP : return ACL_GROUP ;
390+ case POSIXACE4_TAG_MASK : return ACL_MASK ;
391+ case POSIXACE4_TAG_OTHER : return ACL_OTHER ;
392+ }
393+ return ACL_OTHER ;
394+ }
395+
396+ static __be32
397+ nfsd4_decode_posixace4 (struct nfsd4_compoundargs * argp ,
398+ struct posix_acl_entry * ace )
399+ {
400+ posixaceperm4 perm ;
401+ __be32 * p , status ;
402+ posixacetag4 tag ;
403+ u32 len ;
404+
405+ if (!xdrgen_decode_posixacetag4 (argp -> xdr , & tag ))
406+ return nfserr_bad_xdr ;
407+ ace -> e_tag = nfsd4_posixacetag4_to_tag (tag );
408+
409+ if (!xdrgen_decode_posixaceperm4 (argp -> xdr , & perm ))
410+ return nfserr_bad_xdr ;
411+ if (perm & ~S_IRWXO )
412+ return nfserr_bad_xdr ;
413+ ace -> e_perm = perm ;
414+
415+ if (xdr_stream_decode_u32 (argp -> xdr , & len ) < 0 )
416+ return nfserr_bad_xdr ;
417+ p = xdr_inline_decode (argp -> xdr , len );
418+ if (!p )
419+ return nfserr_bad_xdr ;
420+ switch (tag ) {
421+ case POSIXACE4_TAG_USER :
422+ if (len > 0 )
423+ status = nfsd_map_name_to_uid (argp -> rqstp ,
424+ (char * )p , len , & ace -> e_uid );
425+ else
426+ status = nfserr_bad_xdr ;
427+ break ;
428+ case POSIXACE4_TAG_GROUP :
429+ if (len > 0 )
430+ status = nfsd_map_name_to_gid (argp -> rqstp ,
431+ (char * )p , len , & ace -> e_gid );
432+ else
433+ status = nfserr_bad_xdr ;
434+ break ;
435+ default :
436+ status = nfs_ok ;
437+ }
438+
439+ return status ;
440+ }
441+
442+ static noinline __be32
443+ nfsd4_decode_posixacl (struct nfsd4_compoundargs * argp , struct posix_acl * * acl )
444+ {
445+ struct posix_acl_entry * ace ;
446+ __be32 status ;
447+ u32 count ;
448+
449+ if (xdr_stream_decode_u32 (argp -> xdr , & count ) < 0 )
450+ return nfserr_bad_xdr ;
451+
452+ * acl = posix_acl_alloc (count , GFP_KERNEL );
453+ if (* acl == NULL )
454+ return nfserr_resource ;
455+
456+ (* acl )-> a_count = count ;
457+ for (ace = (* acl )-> a_entries ; ace < (* acl )-> a_entries + count ; ace ++ ) {
458+ status = nfsd4_decode_posixace4 (argp , ace );
459+ if (status ) {
460+ posix_acl_release (* acl );
461+ * acl = NULL ;
462+ return status ;
463+ }
464+ }
465+
466+ /*
467+ * posix_acl_valid() requires the ACEs to be sorted.
468+ * If they are already sorted, sort_pacl_range() will return
469+ * after one pass through the ACEs, since it implements bubble sort.
470+ * Note that a count == 0 is used to delete a POSIX ACL and a count
471+ * of 1 or 2 will always be found invalid by posix_acl_valid().
472+ */
473+ if (count >= 3 )
474+ sort_pacl_range (* acl , 0 , count - 1 );
475+
476+ return nfs_ok ;
477+ }
478+
479+ #endif /* CONFIG_NFSD_V4_POSIX_ACLS */
480+
381481static __be32
382482nfsd4_decode_fattr4 (struct nfsd4_compoundargs * argp , u32 * bmval , u32 bmlen ,
383483 struct iattr * iattr , struct nfs4_acl * * acl ,
384- struct xdr_netobj * label , int * umask )
484+ struct xdr_netobj * label , int * umask ,
485+ struct posix_acl * * dpaclp , struct posix_acl * * paclp )
385486{
386487 unsigned int starting_pos ;
387488 u32 attrlist4_count ;
@@ -544,9 +645,40 @@ nfsd4_decode_fattr4(struct nfsd4_compoundargs *argp, u32 *bmval, u32 bmlen,
544645 ATTR_MTIME | ATTR_MTIME_SET | ATTR_DELEG ;
545646 }
546647
648+ * dpaclp = NULL ;
649+ * paclp = NULL ;
650+ #ifdef CONFIG_NFSD_V4_POSIX_ACLS
651+ if (bmval [2 ] & FATTR4_WORD2_POSIX_DEFAULT_ACL ) {
652+ struct posix_acl * dpacl ;
653+
654+ status = nfsd4_decode_posixacl (argp , & dpacl );
655+ if (status )
656+ return status ;
657+ * dpaclp = dpacl ;
658+ }
659+ if (bmval [2 ] & FATTR4_WORD2_POSIX_ACCESS_ACL ) {
660+ struct posix_acl * pacl ;
661+
662+ status = nfsd4_decode_posixacl (argp , & pacl );
663+ if (status ) {
664+ posix_acl_release (* dpaclp );
665+ * dpaclp = NULL ;
666+ return status ;
667+ }
668+ * paclp = pacl ;
669+ }
670+ #endif /* CONFIG_NFSD_V4_POSIX_ACLS */
671+
547672 /* request sanity: did attrlist4 contain the expected number of words? */
548- if (attrlist4_count != xdr_stream_pos (argp -> xdr ) - starting_pos )
673+ if (attrlist4_count != xdr_stream_pos (argp -> xdr ) - starting_pos ) {
674+ #ifdef CONFIG_NFSD_V4_POSIX_ACLS
675+ posix_acl_release (* dpaclp );
676+ posix_acl_release (* paclp );
677+ * dpaclp = NULL ;
678+ * paclp = NULL ;
679+ #endif
549680 return nfserr_bad_xdr ;
681+ }
550682
551683 return nfs_ok ;
552684}
@@ -850,7 +982,8 @@ nfsd4_decode_create(struct nfsd4_compoundargs *argp, union nfsd4_op_u *u)
850982 status = nfsd4_decode_fattr4 (argp , create -> cr_bmval ,
851983 ARRAY_SIZE (create -> cr_bmval ),
852984 & create -> cr_iattr , & create -> cr_acl ,
853- & create -> cr_label , & create -> cr_umask );
985+ & create -> cr_label , & create -> cr_umask ,
986+ & create -> cr_dpacl , & create -> cr_pacl );
854987 if (status )
855988 return status ;
856989
@@ -1001,7 +1134,8 @@ nfsd4_decode_createhow4(struct nfsd4_compoundargs *argp, struct nfsd4_open *open
10011134 status = nfsd4_decode_fattr4 (argp , open -> op_bmval ,
10021135 ARRAY_SIZE (open -> op_bmval ),
10031136 & open -> op_iattr , & open -> op_acl ,
1004- & open -> op_label , & open -> op_umask );
1137+ & open -> op_label , & open -> op_umask ,
1138+ & open -> op_dpacl , & open -> op_pacl );
10051139 if (status )
10061140 return status ;
10071141 break ;
@@ -1019,7 +1153,8 @@ nfsd4_decode_createhow4(struct nfsd4_compoundargs *argp, struct nfsd4_open *open
10191153 status = nfsd4_decode_fattr4 (argp , open -> op_bmval ,
10201154 ARRAY_SIZE (open -> op_bmval ),
10211155 & open -> op_iattr , & open -> op_acl ,
1022- & open -> op_label , & open -> op_umask );
1156+ & open -> op_label , & open -> op_umask ,
1157+ & open -> op_dpacl , & open -> op_pacl );
10231158 if (status )
10241159 return status ;
10251160 break ;
@@ -1346,7 +1481,8 @@ nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, union nfsd4_op_u *u)
13461481 return nfsd4_decode_fattr4 (argp , setattr -> sa_bmval ,
13471482 ARRAY_SIZE (setattr -> sa_bmval ),
13481483 & setattr -> sa_iattr , & setattr -> sa_acl ,
1349- & setattr -> sa_label , NULL );
1484+ & setattr -> sa_label , NULL , & setattr -> sa_dpacl ,
1485+ & setattr -> sa_pacl );
13501486}
13511487
13521488static __be32
0 commit comments