Index: bin/setfacl/setfacl.c =================================================================== --- bin/setfacl/setfacl.c +++ bin/setfacl/setfacl.c @@ -73,6 +73,7 @@ static acl_type_t acl_type = ACL_TYPE_ACCESS; static int handle_file(FTS *ftsp, FTSENT *file); +static acl_t sanitize_inheritance(const FTSENT *file, acl_t acl); static char **stdin_files(void); static void usage(void); @@ -124,16 +125,50 @@ return (files_list); } +static acl_t +sanitize_inheritance(const FTSENT *file, acl_t acl) +{ + acl_t acl_new; + acl_entry_t acl_entry; + acl_flagset_t acl_flagset; + int acl_brand, entry_id; + + acl_get_brand_np(acl, &acl_brand); + if (acl_brand != ACL_BRAND_NFS4) + return (acl); + if (file->fts_info == FTS_D) + return (acl); + acl_new = acl_dup(acl); + if (acl_new == (acl_t)NULL) + return ((acl_t)NULL); + + entry_id = ACL_FIRST_ENTRY; + while (acl_get_entry(acl_new, entry_id, &acl_entry) == 1) { + entry_id = ACL_NEXT_ENTRY; + acl_get_flagset_np(acl_entry, &acl_flagset); + if (acl_get_flag_np(acl_flagset, ACL_ENTRY_INHERIT_ONLY)) { + acl_delete_entry(acl_new, acl_entry); + continue; + } + acl_delete_flag_np(acl_flagset, ACL_ENTRY_FILE_INHERIT + | ACL_ENTRY_DIRECTORY_INHERIT + | ACL_ENTRY_NO_PROPAGATE_INHERIT); + } + + return (acl_new); +} + static int handle_file(FTS *ftsp, FTSENT *file) { - acl_t acl; + acl_t acl, acl_backup; acl_entry_t unused_entry; int local_error, ret; struct sf_entry *entry; bool follow_symlink; local_error = 0; + acl_backup = NULL; switch (file->fts_info) { case FTS_D: /* Do not recurse if -R not specified. */ @@ -198,12 +233,36 @@ switch(entry->op) { case OP_ADD_ACL: + acl_backup = entry->acl; + if (R_flag && acl_type == ACL_TYPE_NFS4) { + if ((entry->acl = sanitize_inheritance(file, + entry->acl)) == (acl_t)NULL) { + local_error++; + break; + } + } local_error += add_acl(entry->acl, entry->entry_number, &acl, file->fts_path); + if (entry->acl != acl_backup) { + acl_free(entry->acl); + entry->acl = acl_backup; + } break; case OP_MERGE_ACL: + acl_backup = entry->acl; + if (R_flag && acl_type == ACL_TYPE_NFS4) { + if ((entry->acl = sanitize_inheritance(file, + entry->acl)) == (acl_t)NULL) { + local_error++; + break; + } + } local_error += merge_acl(entry->acl, &acl, file->fts_path); + if (entry->acl != acl_backup) { + acl_free(entry->acl); + entry->acl = acl_backup; + } need_mask = true; break; case OP_REMOVE_EXT: