forked from Bananymous/banan-os
				
			Kernel: Fix directory permissions
We did not care about X bit in directories and instead used only the R bit for search/read.
This commit is contained in:
		
							parent
							
								
									5887f6bcaa
								
							
						
					
					
						commit
						9e4a87021c
					
				|  | @ -34,6 +34,8 @@ namespace Kernel | |||
| 		BAN::ErrorOr<off_t> tell(int) const; | ||||
| 
 | ||||
| 		BAN::ErrorOr<void> fstat(int fd, struct stat*) const; | ||||
| 		BAN::ErrorOr<void> fstatat(int fd, BAN::StringView path, struct stat* buf, int flag); | ||||
| 		BAN::ErrorOr<void> stat(BAN::StringView absolute_path, struct stat* buf, int flag); | ||||
| 
 | ||||
| 		BAN::ErrorOr<void> close(int); | ||||
| 		void close_all(); | ||||
|  |  | |||
|  | @ -106,6 +106,8 @@ namespace Kernel | |||
| 		BAN::ErrorOr<long> sys_tell(int fd); | ||||
| 
 | ||||
| 		BAN::ErrorOr<long> sys_fstat(int fd, struct stat*); | ||||
| 		BAN::ErrorOr<long> sys_fstatat(int fd, const char* path, struct stat* buf, int flag); | ||||
| 		BAN::ErrorOr<long> sys_stat(const char* path, struct stat* buf, int flag); | ||||
| 
 | ||||
| 		BAN::ErrorOr<void> mount(BAN::StringView source, BAN::StringView target); | ||||
| 
 | ||||
|  |  | |||
|  | @ -38,7 +38,7 @@ namespace Kernel | |||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if (flags & O_EXEC) | ||||
| 		if (flags & (O_EXEC | O_SEARCH)) | ||||
| 		{ | ||||
| 			if (mode().mode & S_IXOTH) | ||||
| 			{ } | ||||
|  |  | |||
|  | @ -133,7 +133,7 @@ namespace Kernel | |||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				if (!inode->can_access(credentials, O_RDONLY)) | ||||
| 				if (!inode->can_access(credentials, O_SEARCH)) | ||||
| 					return BAN::Error::from_errno(EACCES); | ||||
| 
 | ||||
| 				inode = TRY(inode->directory_find_inode(path_part)); | ||||
|  | @ -152,7 +152,7 @@ namespace Kernel | |||
| 				auto target = TRY(inode->link_target()); | ||||
| 				if (target.empty()) | ||||
| 					return BAN::Error::from_errno(ENOENT); | ||||
| 				 | ||||
| 
 | ||||
| 				if (target.front() == '/') | ||||
| 				{ | ||||
| 					inode = root_inode(); | ||||
|  |  | |||
|  | @ -179,11 +179,8 @@ namespace Kernel | |||
| 		return m_open_files[fd]->offset; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<void> OpenFileDescriptorSet::fstat(int fd, struct stat* out) const | ||||
| 	static void read_stat_from_inode(BAN::RefPtr<Inode> inode, struct stat* out) | ||||
| 	{ | ||||
| 		TRY(validate_fd(fd)); | ||||
| 
 | ||||
| 		auto inode = m_open_files[fd]->inode; | ||||
| 		out->st_dev		= inode->dev(); | ||||
| 		out->st_ino		= inode->ino(); | ||||
| 		out->st_mode	= inode->mode().mode; | ||||
|  | @ -197,7 +194,42 @@ namespace Kernel | |||
| 		out->st_ctim	= inode->ctime(); | ||||
| 		out->st_blksize	= inode->blksize(); | ||||
| 		out->st_blocks	= inode->blocks(); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<void> OpenFileDescriptorSet::fstat(int fd, struct stat* out) const | ||||
| 	{ | ||||
| 		TRY(validate_fd(fd)); | ||||
| 		read_stat_from_inode(m_open_files[fd]->inode, out); | ||||
| 		return {}; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<void> OpenFileDescriptorSet::fstatat(int fd, BAN::StringView path, struct stat* out, int flag) | ||||
| 	{ | ||||
| 		if (flag & ~AT_SYMLINK_NOFOLLOW) | ||||
| 			return BAN::Error::from_errno(EINVAL); | ||||
| 		if (flag == AT_SYMLINK_NOFOLLOW) | ||||
| 			flag = O_NOFOLLOW; | ||||
| 
 | ||||
| 		BAN::String absolute_path; | ||||
| 		TRY(absolute_path.append(TRY(path_of(fd)))); | ||||
| 		TRY(absolute_path.push_back('/')); | ||||
| 		TRY(absolute_path.append(path)); | ||||
| 
 | ||||
| 		// FIXME: handle O_SEARCH in fd
 | ||||
| 		auto file = TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, flag)); | ||||
| 		read_stat_from_inode(file.inode, out); | ||||
| 
 | ||||
| 		return {}; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<void> OpenFileDescriptorSet::stat(BAN::StringView absolute_path, struct stat* out, int flag) | ||||
| 	{ | ||||
| 		if (flag & ~AT_SYMLINK_NOFOLLOW) | ||||
| 			return BAN::Error::from_errno(EINVAL); | ||||
| 		if (flag == AT_SYMLINK_NOFOLLOW) | ||||
| 			flag = O_NOFOLLOW; | ||||
| 		auto file = TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, flag)); | ||||
| 		read_stat_from_inode(file.inode, out); | ||||
| 		return {}; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -256,6 +288,8 @@ namespace Kernel | |||
| 	{ | ||||
| 		TRY(validate_fd(fd)); | ||||
| 		auto& open_file = m_open_files[fd]; | ||||
| 		if (!(open_file->flags & O_RDONLY)) | ||||
| 			return BAN::Error::from_errno(EACCES); | ||||
| 		TRY(open_file->inode->directory_read_next_entries(open_file->offset, list, list_size)); | ||||
| 		open_file->offset++; | ||||
| 		return {}; | ||||
|  |  | |||
|  | @ -630,6 +630,8 @@ namespace Kernel | |||
| 	{ | ||||
| 		LockGuard _(m_lock); | ||||
| 
 | ||||
| 		// FIXME: handle O_SEARCH in fd
 | ||||
| 
 | ||||
| 		BAN::String absolute_path; | ||||
| 		TRY(absolute_path.append(TRY(m_open_file_descriptors.path_of(fd)))); | ||||
| 		TRY(absolute_path.push_back('/')); | ||||
|  | @ -737,6 +739,20 @@ namespace Kernel | |||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<long> Process::sys_fstatat(int fd, const char* path, struct stat* buf, int flag) | ||||
| 	{ | ||||
| 		LockGuard _(m_lock); | ||||
| 		TRY(m_open_file_descriptors.fstatat(fd, path, buf, flag)); | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<long> Process::sys_stat(const char* path, struct stat* buf, int flag) | ||||
| 	{ | ||||
| 		LockGuard _(m_lock); | ||||
| 		TRY(m_open_file_descriptors.stat(TRY(absolute_path_of(path)), buf, flag)); | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<long> Process::sys_read_dir_entries(int fd, DirectoryEntryList* list, size_t list_size) | ||||
| 	{ | ||||
| 		LockGuard _(m_lock); | ||||
|  |  | |||
|  | @ -185,6 +185,12 @@ namespace Kernel | |||
| 		case SYS_NANOSLEEP: | ||||
| 			ret = Process::current().sys_nanosleep((const timespec*)arg1, (timespec*)arg2); | ||||
| 			break; | ||||
| 		case SYS_FSTATAT: | ||||
| 			ret = Process::current().sys_fstatat((int)arg1, (const char*)arg2, (struct stat*)arg3, (int)arg4); | ||||
| 			break; | ||||
| 		case SYS_STAT: | ||||
| 			ret = Process::current().sys_stat((const char*)arg1, (struct stat*)arg2, (int)arg3); | ||||
| 			break; | ||||
| 		default: | ||||
| 			dwarnln("Unknown syscall {}", syscall); | ||||
| 			break; | ||||
|  |  | |||
|  | @ -58,7 +58,7 @@ DIR* fdopendir(int fd) | |||
| 
 | ||||
| DIR* opendir(const char* dirname) | ||||
| { | ||||
| 	int fd = open(dirname, O_SEARCH); | ||||
| 	int fd = open(dirname, O_RDONLY); | ||||
| 	if (fd == -1) | ||||
| 		return nullptr; | ||||
| 	return fdopendir(fd); | ||||
|  |  | |||
|  | @ -52,6 +52,8 @@ __BEGIN_DECLS | |||
| #define SYS_SET_PGID 45 | ||||
| #define SYS_FCNTL 46 | ||||
| #define SYS_NANOSLEEP 47 | ||||
| #define SYS_FSTATAT 48 | ||||
| #define SYS_STAT 49 // stat/lstat
 | ||||
| 
 | ||||
| __END_DECLS | ||||
| 
 | ||||
|  |  | |||
|  | @ -11,38 +11,15 @@ int fstat(int fildes, struct stat* buf) | |||
| 
 | ||||
| int fstatat(int fd, const char* __restrict path, struct stat* __restrict buf, int flag) | ||||
| { | ||||
| 	if (flag == AT_SYMLINK_NOFOLLOW) | ||||
| 		flag = O_NOFOLLOW; | ||||
| 	else if (flag) | ||||
| 	{ | ||||
| 		errno = EINVAL; | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	int target = openat(fd, path, O_SEARCH | flag); | ||||
| 	if (target == -1) | ||||
| 		return -1; | ||||
| 	int ret = fstat(target, buf); | ||||
| 	close(target); | ||||
| 	return ret; | ||||
| 	return syscall(SYS_FSTATAT, fd, path, buf, flag); | ||||
| } | ||||
| 
 | ||||
| int lstat(const char* __restrict path, struct stat* __restrict buf) | ||||
| { | ||||
| 	int fd = open(path, O_SEARCH | O_NOFOLLOW); | ||||
| 	if (fd == -1) | ||||
| 		return -1; | ||||
| 	int ret = fstat(fd, buf); | ||||
| 	close(fd); | ||||
| 	return ret; | ||||
| 	return syscall(SYS_STAT, path, buf, AT_SYMLINK_NOFOLLOW); | ||||
| } | ||||
| 
 | ||||
| int stat(const char* __restrict path, struct stat* __restrict buf) | ||||
| { | ||||
| 	int fd = open(path, O_SEARCH); | ||||
| 	if (fd == -1) | ||||
| 		return -1; | ||||
| 	int ret = fstat(fd, buf); | ||||
| 	close(fd); | ||||
| 	return ret; | ||||
| 	return syscall(SYS_STAT, path, buf, 0); | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue