Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mount separated /tmp, /var/tmp partition with noexec, nodev, nosuid options #519

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 110 additions & 0 deletions common/scylla_var_tmp_setup
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright 2019-present ScyllaDB
#

#
# SPDX-License-Identifier: AGPL-3.0-or-later

import os
import sys
import argparse
import psutil
from pathlib import Path
from subprocess import run

def GB(n):
return n * 1024 * 1024 * 1024

def to_GB(n):
return '{:.2f}'.format(n / 1024 / 1024 / 1024)

def find_mount_point(path):
path = path.absolute()
while not path.is_mount():
path = path.parent
return path

def get_fs_type(path):
mnt = find_mount_point(path)
for part in psutil.disk_partitions():
if part.mountpoint == str(mnt):
return part.fstype
return None

if __name__ == '__main__':
if os.getuid() > 0:
print('Requires root permission.')
sys.exit(1)
parser = argparse.ArgumentParser(description='Configure /var/tmp for Scylla.')
parser.add_argument('--var-tmp-directory',
help='specify vartmpfile directory', default='/')
parser.add_argument('--var-tmp-size', type=int,
help='specify vartmpfile size in GB')
parser.add_argument('--var-tmp-size-bytes', type=int,
help='specify vartmpfile size in bytes')
args = parser.parse_args()

var_tmp = Path('/var/tmp')
if find_mount_point(var_tmp).as_posix() == '/var/tmp':
print('/var/tmp already configured, exiting setup')
sys.exit(1)

if args.var_tmp_size and args.var_tmp_size_bytes:
print("Cannot specify both --var-tmp-size and --var-tmp-size-bytes")
sys.exit(1)

var_tmp_directory = Path(args.var_tmp_directory)
vartmpfile = var_tmp_directory / 'vartmpfile'
if vartmpfile.exists():
print('vartmpfile {} already exists'.format(vartmpfile))
sys.exit(1)

vartmpunit_bn = 'var-tmp.mount'
vartmpunit = Path('/etc/systemd/system/{}'.format(vartmpunit_bn))
if vartmpunit.exists():
print('/var/tmp unit {} already exists'.format(vartmpunit))
sys.exit(1)

diskfree = psutil.disk_usage(args.var_tmp_directory).free
if args.var_tmp_size or args.var_tmp_size_bytes:
if args.var_tmp_size:
vartmpsize = GB(args.var_tmp_size)
else:
vartmpsize = args.var_tmp_size_bytes
if vartmpsize > diskfree:
print('Directory {} does not have enough disk space. {}GB space required.'.format(args.var_tmp_directory, to_GB(vartmpsize)))
sys.exit(1)
else:
print('Please specify --var-tmp-size or --var-tmp-size-bytes')
sys.exit(1)

vartmpsize_mb = int(vartmpsize / 1024 / 1024)
fs_type = get_fs_type(var_tmp_directory)
if fs_type == 'ext4':
run(f'fallocate -l {vartmpsize_mb}MiB {vartmpfile}', shell=True, check=True)
else:
run('dd if=/dev/zero of={} bs=1M count={}'.format(vartmpfile, vartmpsize_mb), shell=True, check=True)
vartmpfile.chmod(0o600)
run('mke2fs -t ext4 {}'.format(vartmpfile), shell=True, check=True)
unit_data = '''
[Unit]
Before=local-fs.target
Requires=-.mount
After=-.mount

[Mount]
What={}
Where=/var/tmp
Type=ext4
Options=strictatime,nosuid,nodev,noexec
ReadWriteOnly=True

[Install]
WantedBy=multi-user.target
'''[1:-1].format(vartmpfile)
with vartmpunit.open('w') as f:
f.write(unit_data)
run('systemctl daemon-reload', shell=True, check=True)
run('systemctl enable --now var-tmp.mount', shell=True, check=True)
3 changes: 2 additions & 1 deletion dist/debian/debian/rules
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ override_dh_auto_install:
--with-python3 $(CURDIR)/debian/tmp/opt/scylladb/python3/bin/python3 \
common/scylla_image_setup common/scylla_login common/scylla_configure.py \
common/scylla_create_devices common/scylla_post_start.py \
common/scylla_cloud_io_setup common/scylla_ec2_check
common/scylla_cloud_io_setup common/scylla_ec2_check \
common/scylla_var_tmp_setup

override_dh_installinit:
dh_installinit --no-start --name scylla-image-setup
Expand Down
3 changes: 2 additions & 1 deletion dist/redhat/scylla-machine-image.spec
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ install -m755 common/scylla_configure.py common/scylla_post_start.py common/scyl
--with-python3 ${RPM_BUILD_ROOT}/opt/scylladb/python3/bin/python3 \
common/scylla_image_setup common/scylla_login common/scylla_configure.py \
common/scylla_create_devices common/scylla_post_start.py \
common/scylla_cloud_io_setup common/scylla_ec2_check
common/scylla_cloud_io_setup common/scylla_ec2_check \
common/scylla_var_tmp_setup

%pre
/usr/sbin/groupadd scylla 2> /dev/null || :
Expand Down
16 changes: 14 additions & 2 deletions packer/scylla_install_image
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ if __name__ == '__main__':

run(f'/opt/scylladb/scripts/scylla_sysconfig_setup --set-clocksource', shell=True, check=True)
run('/opt/scylladb/scripts/scylla_coredump_setup', shell=True, check=True)
dot_mount = '''
coredump_dot_mount = '''
[Unit]
Description=Save coredump to scylla data directory
Conflicts=umount.target
Expand All @@ -158,7 +158,7 @@ Options=bind
WantedBy=multi-user.target
'''[1:-1]
with open('/etc/systemd/system/var-lib-systemd-coredump.mount', 'w') as f:
f.write(dot_mount)
f.write(coredump_dot_mount)
os.makedirs('/var/lib/scylla/coredump', exist_ok=True)

os.remove('{}/.ssh/authorized_keys'.format(homedir))
Expand All @@ -178,6 +178,18 @@ WantedBy=multi-user.target
with open(profile, 'a') as f:
f.write('\n\n/opt/scylladb/scylla-machine-image/scylla_login\n')

os.makedirs('/etc/systemd/system/tmp.mount.d', exist_ok=True)
options_conf = '''
[Mount]
Options=
Options=mode=1777,strictatime,nosuid,nodev,noexec,size=50%%,nr_inodes=1m
'''[1:-1]
with open('/etc/systemd/system/tmp.mount.d/options.conf', 'w') as f:
f.write(options_conf)
run('systemctl daemon-reload', shell=True, check=True)
run('systemctl enable --now /usr/share/systemd/tmp.mount', shell=True, check=True)
run('/opt/scylladb/scylla-machine-image/scylla_var_tmp_setup --var-tmp-size 1', shell=True, check=True)

# On AWS, ssh user is statically created at AMI building time, so we need to
# change it to 'scyllaadm`.
# However, on GCE and Azure ssh user is dynamically created at instance startup
Expand Down
Loading