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