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<off_t> tell(int) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		BAN::ErrorOr<void> fstat(int fd, struct stat*) 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);
 | 
							BAN::ErrorOr<void> close(int);
 | 
				
			||||||
		void close_all();
 | 
							void close_all();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -106,6 +106,8 @@ namespace Kernel
 | 
				
			||||||
		BAN::ErrorOr<long> sys_tell(int fd);
 | 
							BAN::ErrorOr<long> sys_tell(int fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		BAN::ErrorOr<long> sys_fstat(int fd, struct stat*);
 | 
							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);
 | 
							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)
 | 
								if (mode().mode & S_IXOTH)
 | 
				
			||||||
			{ }
 | 
								{ }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -133,7 +133,7 @@ namespace Kernel
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				if (!inode->can_access(credentials, O_RDONLY))
 | 
									if (!inode->can_access(credentials, O_SEARCH))
 | 
				
			||||||
					return BAN::Error::from_errno(EACCES);
 | 
										return BAN::Error::from_errno(EACCES);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				inode = TRY(inode->directory_find_inode(path_part));
 | 
									inode = TRY(inode->directory_find_inode(path_part));
 | 
				
			||||||
| 
						 | 
					@ -152,7 +152,7 @@ namespace Kernel
 | 
				
			||||||
				auto target = TRY(inode->link_target());
 | 
									auto target = TRY(inode->link_target());
 | 
				
			||||||
				if (target.empty())
 | 
									if (target.empty())
 | 
				
			||||||
					return BAN::Error::from_errno(ENOENT);
 | 
										return BAN::Error::from_errno(ENOENT);
 | 
				
			||||||
				
 | 
					
 | 
				
			||||||
				if (target.front() == '/')
 | 
									if (target.front() == '/')
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					inode = root_inode();
 | 
										inode = root_inode();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -179,11 +179,8 @@ namespace Kernel
 | 
				
			||||||
		return m_open_files[fd]->offset;
 | 
							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_dev		= inode->dev();
 | 
				
			||||||
		out->st_ino		= inode->ino();
 | 
							out->st_ino		= inode->ino();
 | 
				
			||||||
		out->st_mode	= inode->mode().mode;
 | 
							out->st_mode	= inode->mode().mode;
 | 
				
			||||||
| 
						 | 
					@ -197,7 +194,42 @@ namespace Kernel
 | 
				
			||||||
		out->st_ctim	= inode->ctime();
 | 
							out->st_ctim	= inode->ctime();
 | 
				
			||||||
		out->st_blksize	= inode->blksize();
 | 
							out->st_blksize	= inode->blksize();
 | 
				
			||||||
		out->st_blocks	= inode->blocks();
 | 
							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 {};
 | 
							return {};
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -256,6 +288,8 @@ namespace Kernel
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		TRY(validate_fd(fd));
 | 
							TRY(validate_fd(fd));
 | 
				
			||||||
		auto& open_file = m_open_files[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));
 | 
							TRY(open_file->inode->directory_read_next_entries(open_file->offset, list, list_size));
 | 
				
			||||||
		open_file->offset++;
 | 
							open_file->offset++;
 | 
				
			||||||
		return {};
 | 
							return {};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -630,6 +630,8 @@ namespace Kernel
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		LockGuard _(m_lock);
 | 
							LockGuard _(m_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// FIXME: handle O_SEARCH in fd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		BAN::String absolute_path;
 | 
							BAN::String absolute_path;
 | 
				
			||||||
		TRY(absolute_path.append(TRY(m_open_file_descriptors.path_of(fd))));
 | 
							TRY(absolute_path.append(TRY(m_open_file_descriptors.path_of(fd))));
 | 
				
			||||||
		TRY(absolute_path.push_back('/'));
 | 
							TRY(absolute_path.push_back('/'));
 | 
				
			||||||
| 
						 | 
					@ -737,6 +739,20 @@ namespace Kernel
 | 
				
			||||||
		return 0;
 | 
							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)
 | 
						BAN::ErrorOr<long> Process::sys_read_dir_entries(int fd, DirectoryEntryList* list, size_t list_size)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		LockGuard _(m_lock);
 | 
							LockGuard _(m_lock);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -185,6 +185,12 @@ namespace Kernel
 | 
				
			||||||
		case SYS_NANOSLEEP:
 | 
							case SYS_NANOSLEEP:
 | 
				
			||||||
			ret = Process::current().sys_nanosleep((const timespec*)arg1, (timespec*)arg2);
 | 
								ret = Process::current().sys_nanosleep((const timespec*)arg1, (timespec*)arg2);
 | 
				
			||||||
			break;
 | 
								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:
 | 
							default:
 | 
				
			||||||
			dwarnln("Unknown syscall {}", syscall);
 | 
								dwarnln("Unknown syscall {}", syscall);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,7 +58,7 @@ DIR* fdopendir(int fd)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DIR* opendir(const char* dirname)
 | 
					DIR* opendir(const char* dirname)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int fd = open(dirname, O_SEARCH);
 | 
						int fd = open(dirname, O_RDONLY);
 | 
				
			||||||
	if (fd == -1)
 | 
						if (fd == -1)
 | 
				
			||||||
		return nullptr;
 | 
							return nullptr;
 | 
				
			||||||
	return fdopendir(fd);
 | 
						return fdopendir(fd);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -52,6 +52,8 @@ __BEGIN_DECLS
 | 
				
			||||||
#define SYS_SET_PGID 45
 | 
					#define SYS_SET_PGID 45
 | 
				
			||||||
#define SYS_FCNTL 46
 | 
					#define SYS_FCNTL 46
 | 
				
			||||||
#define SYS_NANOSLEEP 47
 | 
					#define SYS_NANOSLEEP 47
 | 
				
			||||||
 | 
					#define SYS_FSTATAT 48
 | 
				
			||||||
 | 
					#define SYS_STAT 49 // stat/lstat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__END_DECLS
 | 
					__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)
 | 
					int fstatat(int fd, const char* __restrict path, struct stat* __restrict buf, int flag)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (flag == AT_SYMLINK_NOFOLLOW)
 | 
						return syscall(SYS_FSTATAT, fd, path, buf, flag);
 | 
				
			||||||
		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;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int lstat(const char* __restrict path, struct stat* __restrict buf)
 | 
					int lstat(const char* __restrict path, struct stat* __restrict buf)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int fd = open(path, O_SEARCH | O_NOFOLLOW);
 | 
						return syscall(SYS_STAT, path, buf, AT_SYMLINK_NOFOLLOW);
 | 
				
			||||||
	if (fd == -1)
 | 
					 | 
				
			||||||
		return -1;
 | 
					 | 
				
			||||||
	int ret = fstat(fd, buf);
 | 
					 | 
				
			||||||
	close(fd);
 | 
					 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int stat(const char* __restrict path, struct stat* __restrict buf)
 | 
					int stat(const char* __restrict path, struct stat* __restrict buf)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int fd = open(path, O_SEARCH);
 | 
						return syscall(SYS_STAT, path, buf, 0);
 | 
				
			||||||
	if (fd == -1)
 | 
					 | 
				
			||||||
		return -1;
 | 
					 | 
				
			||||||
	int ret = fstat(fd, buf);
 | 
					 | 
				
			||||||
	close(fd);
 | 
					 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue