blob: c0f66b0cec11f02823900895179c2f54cafb2d76 [file] [log] [blame]
// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "cros-disks/fuse_mounter.h"
#include <linux/capability.h>
#include <string>
#include <base/file_util.h>
#include <base/logging.h>
#include "cros-disks/platform.h"
#include "cros-disks/sandboxed_process.h"
using base::FilePath;
using std::string;
namespace {
// Process capabilities required by the FUSE mount process:
// CAP_SYS_ADMIN for mounting/unmounting filesystem
// CAP_SETUID/CAP_SETGID for setting uid/gid in non-privileged mounts
const uint64_t kMountProgramCapabilities =
(1 << CAP_SYS_ADMIN) | (1 << CAP_SETUID) | (1 << CAP_SETGID);
const mode_t kSourcePathPermissions = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
const mode_t kTargetPathPermissions = S_IRWXU | S_IRWXG;
} // namespace
namespace cros_disks {
FUSEMounter::FUSEMounter(const string& source_path,
const string& target_path,
const string& filesystem_type,
const MountOptions& mount_options,
const Platform* platform,
const string& mount_program_path,
const string& mount_user)
: Mounter(source_path, target_path, filesystem_type, mount_options),
platform_(platform),
mount_program_path_(mount_program_path),
mount_user_(mount_user) {
}
MountErrorType FUSEMounter::MountImpl() {
if (!base::PathExists(FilePath(mount_program_path_))) {
LOG(ERROR) << "Failed to find the FUSE mount program";
return MOUNT_ERROR_MOUNT_PROGRAM_NOT_FOUND;
}
SandboxedProcess mount_process;
mount_process.SetCapabilities(kMountProgramCapabilities);
uid_t mount_user_id;
gid_t mount_group_id;
// To perform a non-privileged mount via the FUSE mount program, change the
// group of the source and target path to the group of the non-privileged
// user, but keep the user of the source and target path unchanged. Also set
// appropriate group permissions on the source and target path.
if (!platform_->GetUserAndGroupId(mount_user_,
&mount_user_id, &mount_group_id) ||
!platform_->SetOwnership(source_path(), getuid(), mount_group_id) ||
!platform_->SetPermissions(source_path(), kSourcePathPermissions) ||
!platform_->SetOwnership(target_path(), getuid(), mount_group_id) ||
!platform_->SetPermissions(target_path(), kTargetPathPermissions)) {
return MOUNT_ERROR_INTERNAL;
}
mount_process.SetUserId(mount_user_id);
mount_process.SetGroupId(mount_group_id);
mount_process.AddArgument(mount_program_path_);
string options_string = mount_options().ToString();
if (!options_string.empty()) {
mount_process.AddArgument("-o");
mount_process.AddArgument(options_string);
}
mount_process.AddArgument(source_path());
mount_process.AddArgument(target_path());
int return_code = mount_process.Run();
if (return_code != 0) {
LOG(WARNING) << "FUSE mount program failed with a return code "
<< return_code;
return MOUNT_ERROR_MOUNT_PROGRAM_FAILED;
}
return MOUNT_ERROR_NONE;
}
} // namespace cros_disks