使oracle运行在selinux中的实践-附源代码

来源:互联网 发布:思迅天店软件怎么用 编辑:程序博客网 时间:2024/05/06 18:42

已经差不多1年半没有发文了,眼看着2012即将成为过去,看着荒草丛生的博客,心中想着还是发点什么东西,也许会帮到别人。同时,也聊以自慰自己还在技术圈混呢。


2011年初,在一次安装体验FC14的过程中注意到了其已经很完善的SELinux模块。记得在几年前第一次看到Linux发行版中的SELinux简直认为就是个鸡肋,什么都不能运行。但在FC14中大量的模块使我映像深刻,所有系统的默认服务:比如,httpd,ftpd,mysql等等都有了相应的安全策略模块,而且都可以在开启SELinux的情况下使用这些服务,注意,带来的好处是系统运行在SELinux 的enforcing的安全策略上下文中-即MAC(Mandatory Access Control),那就是说这里的web服务器将比任何一个不运行SELinux的web服务器安全的多,黑客的入侵基本上不可能。技术人员的天生的学习欲望驱使我开始学些并挖掘如何能最大化SELinux的优点,并为我所用。当时,正好碰到一个问题,我安装的Oracle服务器无法启动,当时忘记了系统默认是SELinux开启的。最后经过一番苦斗才无意中发现了/var/log/audit.log中尽然有大量被Denied请求,而且进程都是oracle的进程,才意识到是SELinux阻止了oracle进程运行。所以,作为一个学习SELinux练习和实践,开始练习如何自己创建SELinux模块,以使某一个服务能够运行于其安全上下文的实践。

过程不是很长,大概1个多星期的所有业余时间,最终完成了创建oracle SELinux模块。也对整个SELinux的架构有了深刻的了解。设计细节就不讲太多了,直接上结果和代码。也许有人需要(据我了解oracle他们给客户的解决方案仍然停留在:停止SELinux,运行Oracle 层面 :-))

这是ps的截屏:

可以看到oracle的进程运行在一个自定义的安全上下文unconfined_u:system_r:oradb_t:SystemLow 中。 oradb_t是进程运行的域(Domain)-我大致按照SELinux命名习惯起的名字。后面在相关代码将看到更多命名。


这是相关文件一览。

于2011-02-16上传最后一次修改,到2012年年底才发文,我太懒了:-(

模块源文件介绍:

oradb.fc  - SELinux模块的文件上下文(file context)定义,或安全上下文定义。我们将需要用restorecon或setfiles工具 重新label文件系统,使所有这里定义的文件具有我们所设计的安全上下文。

oradb.if  - SELinux接口定义。我还没有想到代码重用的必要,所以并没有设计可重用的接口,所以这个文件是空的,只有一行注释。我也不贴内容了。

oradb.te  - 这就是SELinux安全策略源文件。所有的访问,运行,以及域转换的策略都定义于此。

oradb.pp -  这不是源文件,只是上面的3个源文件编译后生成的目标代码。使用semodule工具进行安装。


源文件oradb.fc

# dbora executable will have:# label: system_u:object_r:oradb_exec_t# MLS sensitivity: s0# MCS categories: <none>## ORACLE_HOME#/usr/share/oracle/product/11.2.0/dbhome_1(/.*)?         gen_context(system_u:object_r:oradb_dbhome_content_t,s0)/usr/share/oracle/product/11.2.0/dbhome_1/.*\.log  --      gen_context(system_u:object_r:oradb_log_t,s0)/usr/share/oracle/product/11.2.0/dbhome_1(/.*)?/bin/.*      gen_context(system_u:object_r:oradb_exec_t,s0)/usr/share/oracle/product/11.2.0/dbhome_1/lib(/.*)?gen_context(system_u:object_r:lib_t,s0)## /usr/share/oracle/diag#/usr/share/oracle/diag(/.*)?            gen_context(system_u:object_r:oradb_diag_content_t,s0)## /usr/share/oracle/admin#/usr/share/oracle/admin(/.*)?            gen_context(system_u:object_r:oradb_admin_content_t,s0)## /usr/share/oracle/flash_recovery_area#/usr/share/oracle/flash_recovery_area(/.*)?            gen_context(system_u:object_r:oradb_flash_recovery_area_t,s0)## /usr/share/oracle/cfgtoollogs#/usr/share/oracle/cfgtoollogs(/.*)?            gen_context(system_u:object_r:oradb_cfgtoollogs_t,s0)/usr/share/oracle/cfgtoollogs(/.*)?\.log  --      gen_context(system_u:object_r:oradb_log_t,s0)## /usr/share/oraInventory#/usr/share/oraInventory(/.*)?           gen_context(system_u:object_r:oraInventory_home_t,s0)## /etc#/etc/rc\.d/init\.d/dbora--gen_context(system_u:object_r:oradb_initrc_exec_t,s0)/etc/oratab--gen_context(system_u:object_r:oradb_etc_t,s0)## /var#/var/lock/subsys/dbora--gen_context(system_u:object_r:oradb_var_lock_t,s0)/var/spool/cron/oracle  --  gen_context(system_u:object_r:user_cron_spool_t,s0)## /repo#/repo/oradata(/.*)?gen_context(system_u:object_r:oradb_db_t,s0)


注意:我把oracle安装到/usr/share/oracle目录中的,数据文件(表空间)放在/repo/oradata,生产环境这样做不好。如果你要用这代码,自己修改吧。

源文件oradb.te

policy_module(oradb,1.0.0)########################################## Declarations#type oradb_t;type oradb_exec_t;type oradb_dbhome_content_t;type oradb_diag_content_t;type oradb_admin_content_t;type oradb_flash_recovery_area_t;type oraInventory_home_t;type oradb_cfgtoollogs_t;allow oradb_t oradb_dbhome_content_t:dir { rw_dir_perms setattr };allow oradb_t oradb_dbhome_content_t:file { manage_file_perms exec_file_perms };allow initrc_t oradb_dbhome_content_t:dir search;allow oradb_t oradb_diag_content_t:dir { rw_dir_perms setattr };allow oradb_t oradb_diag_content_t:file manage_file_perms;allow oradb_t oradb_admin_content_t:dir rw_dir_perms;allow oradb_t oradb_admin_content_t:file manage_file_perms;allow oradb_t oradb_flash_recovery_area_t:dir rw_dir_perms;allow oradb_t oradb_flash_recovery_area_t:file manage_file_perms;allow oradb_t oraInventory_home_t:dir { rw_dir_perms setattr };allow oradb_t oraInventory_home_t:file manage_file_perms;allow oradb_t oradb_cfgtoollogs_t:dir { rw_dir_perms setattr };allow oradb_t oradb_cfgtoollogs_t:file manage_file_perms;allow oradb_t tmpfs_t:dir rw_dir_perms;allow oradb_t tmpfs_t:file { manage_file_perms exec_file_perms };allow oradb_t tmpfs_t:filesystem getattr;gen_require(`        type sysfs_t;')allow oradb_t sysfs_t:file { read open getattr };allow oradb_t sysfs_t:dir { search read open };allow oradb_t sysfs_t:filesystem { getattr };allow oradb_t sysfs_t:lnk_file read;# for read fontgen_require(`        type fonts_t;')gen_require(`        type fonts_cache_t;')allow oradb_t fonts_t:dir { search read open getattr };allow oradb_t fonts_t:file { read open getattr };allow oradb_t usr_t:file { read open getattr };allow oradb_t fonts_cache_t:dir { search };allow oradb_t fonts_cache_t:file { read open getattr };# allow /dev/urandom & /dev/randomgen_require(`        type urandom_device_t;')gen_require(`        type random_device_t;')allow oradb_t urandom_device_t:chr_file { getattr read open ioctl };allow oradb_t random_device_t:chr_file { getattr read open ioctl };gen_require(`        type ping_exec_t;')gen_require(`        type ifconfig_exec_t;')allow oradb_t ping_exec_t:file { execute read open execute_no_trans };allow oradb_t ifconfig_exec_t:file { getattr execute read open execute_no_trans };# for sysctlgen_require(`        type binfmt_misc_fs_t;')allow oradb_t binfmt_misc_fs_t:dir { getattr read open search };allow oradb_t binfmt_misc_fs_t:file { getattr read open };fstools_domtrans(oradb_t)allow fsadm_t oradb_dbhome_content_t:dir { search getattr };fstools_getattr_swap_files(oradb_t)gen_require(`        type fixed_disk_device_t;')allow oradb_t fixed_disk_device_t:blk_file read_blk_file_perms;#for mountmount_domtrans(oradb_t)#for lvmgen_require(`        type lvm_exec_t;')allow oradb_t lvm_exec_t:file getattr;storage_getattr_removable_dev(oradb_t)gen_require(`        type setroubleshootd_t;')allow setroubleshootd_t oradb_dbhome_content_t:dir list_dir_perms;allow setroubleshootd_t oradb_diag_content_t:dir list_dir_perms;# can make crond_t (unconfined_t) transit into oradb_tgen_require(`        type unconfined_t;')gen_require(`        type crond_t;')# for cron# crond will executing in crond_t domain, it will fork several times,# so the cronjob will executing in grandchild process of crond, # and cronjob will executing in domain of cron user's default security context.# normally, it is unconfined_u:unconfined_r:unconfined_t:s0. with MLS_LEVEL set# to level. so we need transit from unconfined_t -> oradb_t. and oradb_t domain# need send sigchld to grandparent crond_t.domain_auto_trans(unconfined_t,oradb_exec_t,oradb_t)allow unconfined_t oradb_dbhome_content_t:dir list_dir_perms;allow unconfined_t oradb_dbhome_content_t:file manage_file_perms;# this is for allow a combin of unconfined_r:oradb_trole unconfined_r types oradb_t;allow oradb_t crond_t:process sigchld;fs_associate(oradb_diag_content_t)fs_associate(oradb_dbhome_content_t)fs_associate(oradb_admin_content_t)# /home/oracle search getattr, /home searchuserdom_getattr_user_home_dirs(oradb_t)userdom_search_user_home_dirs(oradb_t)allow oradb_t user_tmp_t:dir { setattr write remove_name add_name };userdom_manage_user_tmp_sockets(oradb_t)corenet_tcp_bind_generic_node(oradb_t)corenet_tcp_bind_generic_port(oradb_t)corenet_tcp_connect_xserver_port(oradb_t)corenet_tcp_connect_snmp_port(oradb_t)# create a domain type that can be entered from initrc_t domaininit_daemon_domain(oradb_t, oradb_exec_t)role system_r types oradb_t;# create file type oradb_initrc_exec_t that can transit into initrc_t domaintype oradb_initrc_exec_t;init_script_file(oradb_initrc_exec_t)#create file type oradb_etc_t as configfiletype oradb_etc_t;files_config_file(oradb_etc_t)type oradb_db_t;files_type(oradb_db_t)type oradb_var_lock_t;files_lock_file(oradb_var_lock_t)#create oradb_log_t as a logfile.type oradb_log_t;logging_log_file(oradb_log_t)#allow rw in /var/log and create oradb_log_tlogging_log_filetrans(oradb_t, oradb_log_t, file)# complete manage on file oradb_log_tmanage_files_pattern(oradb_t, oradb_log_t, oradb_log_t)logging_send_syslog_msg(oradb_t)logging_send_audit_msgs(oradb_t)allow oradb_t oradb_var_lock_t:file manage_file_perms;files_lock_filetrans(initrc_t, oradb_var_lock_t, file)# complete permssion to ora db file and dirsmanage_dirs_pattern(oradb_t, oradb_db_t, oradb_db_t)manage_files_pattern(oradb_t, oradb_db_t, oradb_db_t)manage_lnk_files_pattern(oradb_t, oradb_db_t, oradb_db_t)manage_fifo_files_pattern(oradb_t, oradb_db_t, oradb_db_t)manage_sock_files_pattern(oradb_t, oradb_db_t, oradb_db_t)# allow to read locale_tmiscfiles_read_localization(oradb_t)# allow /proc/meminfokernel_read_system_state(oradb_t)# allow read /etc/resolv.conf, perform DNS name resolv. a lot of staff here.sysnet_dns_name_resolve(oradb_t)# exec hostname in oradb_t domain, without transition.hostname_exec(oradb_t)files_read_etc_files(oradb_t)allow oradb_t self:capability { kill dac_override dac_read_search chown fowner fsetid setuid setgid sys_nice sys_tty_config sys_admin sys_rawio };allow oradb_t self:process { signal_perms execmem execstack setsched setpgid };allow oradb_t self:fifo_file rw_fifo_file_perms;allow oradb_t self:file { getattr read };allow oradb_t self:sem create_sem_perms;allow oradb_t self:shm create_shm_perms;allow oradb_t self:tcp_socket create_stream_socket_perms;allow oradb_t self:udp_socket create_stream_socket_perms;allow oradb_t self:unix_dgram_socket create_socket_perms;allow oradb_t self:unix_stream_socket { create_stream_socket_perms connectto };allow oradb_t self:netlink_selinux_socket create_socket_perms;allow oradb_t self:rawip_socket { create setopt getopt read write };allow oradb_t self:capability net_raw;#for node_bind requestcorenet_udp_bind_generic_node(oradb_t)# for netlink_route_socketallow oradb_t self:netlink_route_socket r_netlink_socket_perms;# allow port:tcp_socket name_connectcorenet_tcp_connect_generic_port(oradb_t)# can exec grep,cutcorecmd_exec_bin(oradb_t)# can exec shellcorecmd_exec_shell(oradb_t)# can exec solibs_legacy_use_shared_libs(oradb_t)# can read /proc/1init_read_state(oradb_t)# for lspcigen_require(`        type hwdata_t;')gen_require(`        type modules_object_t;')gen_require(`        type modules_dep_t;')allow oradb_t hwdata_t:dir search;allow oradb_t hwdata_t:file { open read getattr };allow oradb_t modules_object_t:dir search;allow oradb_t modules_object_t:file { open read getattr };allow oradb_t modules_dep_t:file { open read getattr };# for uptimegen_require(`        type initrc_var_run_t;')gen_require(`        type rpc_pipefs_t;')allow oradb_t initrc_var_run_t:file { open read lock };# for dfgen_require(`        type samba_share_t;')gen_require(`        type var_lib_nfs_t;')allow oradb_t { devpts_t binfmt_misc_fs_t rpc_pipefs_t }:filesystem getattr;allow oradb_t { samba_share_t var_lib_nfs_t }:dir { getattr search };# for shgen_require(`        type dmesg_exec_t;')allow oradb_t dmesg_exec_t:file { execute read open execute_no_trans getattr };# for rpm, I don't want role transitiondomain_system_change_exemption(oradb_t)rpm_domtrans(oradb_t)allow rpm_t oradb_dbhome_content_t:dir { search getattr };gen_require(`        type sysstat_log_t;')allow oradb_t sysstat_log_t:file read;# read all sysctl_type, for ex: sysctl_net_t, sysctl_t, proc_net_t,sysctl_fs_t etc.kernel_read_all_sysctls(oradb_t)allow oradb_t proc_net_t:file read_file_perms;# allow to access /tmp dir and fileallow oradb_t tmp_t:dir manage_dir_perms;allow oradb_t tmp_t:file manage_file_perms;# allow fs_t:filesystem / getattrfs_getattr_xattr_fs(oradb_t)#  execute_no_transcan_exec(oradb_t,oradb_exec_t)allow oradb_t oradb_exec_t:lnk_file { getattr read };# make a fake decl to use in here for sysctl_kernel_t which have been declared in kernel.te, actuall sysctl_kernel_t is a sysctl_type :-)gen_require(`        type sysctl_kernel_t;')allow oradb_t sysctl_kernel_t:dir search;allow oradb_t sysctl_kernel_t:file read;gen_require(`        type kernel_t;')allow oradb_t kernel_t:dir { search read getattr };allow oradb_t kernel_t:file { read open };allow oradb_t kernel_t:system { syslog_read ipc_info };# prevent ps command from flushing audit.log, no priviledge to do this on most of pid.# do not use *! only neverallow suport * and ~#dontaudit oradb_t *:{ dir file } { getattr search read open };domain_dontaudit_read_all_domains_state(oradb_t)allow oradb_t self:capability sys_ptrace;# for dbca/emcagen_require(`type xauth_home_t;')allow oradb_t xauth_home_t:file { getattr read open };allow oradb_t oradb_dbhome_content_t:dir create;allow oradb_cfgtoollogs_t fs_t:filesystem associate;

我都写有注释的,想用的人看看还是有帮助的。

不要怪我没说,研究selinux可能会耗尽你的生命 微笑,珍惜生命者莫入。如果你想build自己的CIA级别安全系统,那么你可能需要这样做。

该模块还是比较简单的,仍然是基于enforcing policy的MAC实现。可以简单方便的应用于RH或FC血统的Linux发行。没试过其他。也许可以也许需要结构的修改。

对于更高级别的安全实现,比如MLS/MCS/RBACS - 多级安全-多敏感度安全/多范畴安全/基于角色的访问控制安全,那SELinux需要进行重新配置,以支持MLS/MCS/RBACS 策略,这个模块的安全上下文和policy需要重新设计。这已经超出我目前的知识范畴,需要更多学习,需要更多的生命去完成微笑,目前不打算这样浪费我的青春了-虽然已经青春不再。

现在SELinux在中国的应用还非常少,在国外也是如此,有同事告诉我CIA在用类似的系统。我估计看过美剧《24小时》的人都注意到CTU总部里面的安全系统,随时可以提高级别或者降低级别,以致于有些人一下就不可以访问了,一下又可以了。其实它就是一个MLS/MCS/RBACS的安全系统例子。


SELinux固然可以大大提高系统的安全性,可以说几乎不可攻破(我坚信世上没有绝对,所以不能说绝对不能)。但代价是它会使系统管理员的维护/诊断工作量大量增加。所以,在一个要求安全性非常高的系统中。也许值得这样做。

原创粉丝点击