struct security_descriptor *get_file_sd( struct object *obj, struct fd *fd, mode_t *mode, uid_t *uid ) { int unix_fd = get_unix_fd( fd ); struct stat st; struct security_descriptor *sd; const SID *user, *group; if (unix_fd == -1 || fstat( unix_fd, &st ) == -1) return obj->sd; /* mode and uid the same? if so, no need to re-generate security descriptor */ if (obj->sd && (st.st_mode & (S_IRWXU|S_IRWXO)) == (*mode & (S_IRWXU|S_IRWXO)) && (st.st_uid == *uid)) return obj->sd; user = security_unix_uid_to_sid( st.st_uid ); group = token_get_primary_group( current->process->token ); sd = get_xattr_sd( unix_fd ); if (!sd) sd = get_xattr_acls( unix_fd, user, group ); if (sd) convert_generic_sd( sd ); if (!sd) sd = mode_to_sd( st.st_mode, user, group ); if (!sd) return obj->sd; *mode = st.st_mode; *uid = st.st_uid; free( obj->sd ); obj->sd = sd; return sd; }
static struct security_descriptor *file_get_sd( struct object *obj ) { struct file *file = (struct file *)obj; struct stat st; int unix_fd; struct security_descriptor *sd; assert( obj->ops == &file_ops ); unix_fd = get_file_unix_fd( file ); if (unix_fd == -1 || fstat( unix_fd, &st ) == -1) return obj->sd; /* mode and uid the same? if so, no need to re-generate security descriptor */ if (obj->sd && (st.st_mode & (S_IRWXU|S_IRWXO)) == (file->mode & (S_IRWXU|S_IRWXO)) && (st.st_uid == file->uid)) return obj->sd; sd = mode_to_sd( st.st_mode, security_unix_uid_to_sid( st.st_uid ), token_get_primary_group( current->process->token )); if (!sd) return obj->sd; file->mode = st.st_mode; file->uid = st.st_uid; free( obj->sd ); obj->sd = sd; return sd; }
static struct security_descriptor *file_get_parent_sd( struct fd *root, const char *child_name, int child_len, int is_dir ) { struct security_descriptor *parent_sd, *sd = NULL; mode_t parent_mode = 0555; char *p, *parent_name; struct fd *parent_fd; struct stat st; int unix_fd; if (!(parent_name = mem_alloc( child_len + 1 ))) return NULL; memcpy( parent_name, child_name, child_len ); parent_name[child_len] = 0; /* skip trailing slashes */ p = parent_name + strlen( parent_name ) - 1; while (p > parent_name && *p == '/') p--; /* remove last path component */ if (p == parent_name && *p == '/') { free(parent_name); return NULL; } while (p > parent_name && *p != '/') p--; while (p > parent_name && *p == '/') p--; p[1] = 0; parent_fd = open_fd( root, parent_name, O_NONBLOCK | O_LARGEFILE, &parent_mode, READ_CONTROL|ACCESS_SYSTEM_SECURITY, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN_FOR_BACKUP_INTENT ); free( parent_name ); if (parent_fd) { unix_fd = get_unix_fd( parent_fd ); if (unix_fd != -1) { parent_sd = get_xattr_sd( unix_fd ); if (!parent_sd && fstat( unix_fd, &st ) != -1) parent_sd = get_xattr_acls( unix_fd, security_unix_uid_to_sid( st.st_uid ), token_get_primary_group( current->process->token ) ); if (parent_sd) { sd = inherit_sd( parent_sd, is_dir ); free( parent_sd ); } } release_object( parent_fd ); } return sd; }