2005-06-02 14:31:31 +00:00
|
|
|
########################################
|
2016-12-01 17:12:34 +00:00
|
|
|
#
|
2005-06-08 20:23:12 +00:00
|
|
|
# Support macros for sets of object classes and permissions
|
2005-06-02 14:31:31 +00:00
|
|
|
#
|
2005-06-08 20:23:12 +00:00
|
|
|
# This file should only have object class and permission set macros - they
|
|
|
|
# can only reference object classes and/or permissions.
|
2005-06-02 14:31:31 +00:00
|
|
|
|
2016-12-01 17:12:34 +00:00
|
|
|
|
|
|
|
########################################
|
|
|
|
#
|
|
|
|
# Macros for sets of classes
|
|
|
|
#
|
|
|
|
|
2005-06-02 14:31:31 +00:00
|
|
|
#
|
|
|
|
# All directory and file classes
|
|
|
|
#
|
2016-12-01 17:12:34 +00:00
|
|
|
define(`dir_file_class_set', `{ dir file_class_set }')
|
2005-06-02 14:31:31 +00:00
|
|
|
|
|
|
|
#
|
|
|
|
# All non-directory file classes.
|
|
|
|
#
|
2016-12-01 17:12:34 +00:00
|
|
|
define(`file_class_set', `{ devfile_class_set notdevfile_class_set }')
|
2005-06-02 14:31:31 +00:00
|
|
|
|
|
|
|
#
|
|
|
|
# Non-device file classes.
|
|
|
|
#
|
2016-12-01 17:12:34 +00:00
|
|
|
define(`notdevfile_class_set', `{ fifo_file file lnk_file sock_file }')
|
2005-06-02 14:31:31 +00:00
|
|
|
|
|
|
|
#
|
|
|
|
# Device file classes.
|
|
|
|
#
|
2016-12-01 17:12:34 +00:00
|
|
|
define(`devfile_class_set', `{ blk_file chr_file }')
|
2005-06-02 14:31:31 +00:00
|
|
|
|
|
|
|
#
|
|
|
|
# All socket classes.
|
|
|
|
#
|
Rename obsolete netlink_firewall_socket and netlink_ip6fw_socket classes
The implementation for NETLINK_FIREWALL and NETLINK_IP6_FW protocols
was removed from the kernel in commit
d16cf20e2f2f13411eece7f7fb72c17d141c4a84 ("netfilter: remove ip_queue
support") circa Linux 3.5. Consequently, kernels >= 3.5 should never
perform permission checks on these classes although they remained
defined in the SELinux kernel classmap until the netlink classes
were updated by
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6c6d2e9bde1c1c87a7ead806f8f5e2181d41a652
circa Linux v4.2.
Removing these class definitions would break legacy userspace that relies
upon stable values for the userspace security class definitions since it
will perturb those values by removing classes that preceded them. dbus-daemon
in particular is known to break if its dbus class changes at runtime,
which could occur upon a policy reload that removes these classes.
Fixing this requires ensuring that dbus-daemon looks up the appropriate
class value on each use or upon policy reload, via userspace interfaces
such as selinux_check_access(), string_to_security_class(), and/or
selinux_set_callback(SELINUX_CB_POLICYLOAD, ...) with a callback function
that remaps the class value if needed. Other userspace policy enforcers
are believed to have been updated in recent versions but older versions
may break upon such a change.
Hence, this change renames these classes with obsolete_ prefixes and
removes all rules referencing them from refpolicy, thereby preserving
the class numbering for subsequent classes while making it clear that
these classses are no longer meaningful for modern kernels.
This change does however create a potential compatibility break for
kernels < 3.5, since the policy will cease to define the kernel class
names and therefore the kernel will handle permission checks on the
class based on the handle_unknown setting in policy. For most
Linux distributions, this will default to allow and therefore avoid
breaking userspace but will fail open. For kernels < 2.6.33 (i.e.
the dynamic class/perm discovery support), the presence of a class
in policy with the same number but a different name than the kernel
class will cause the policy load to fail entirely.
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
2020-01-14 15:31:00 +00:00
|
|
|
define(`socket_class_set', `{ tcp_socket udp_socket rawip_socket netlink_socket packet_socket unix_stream_socket unix_dgram_socket appletalk_socket netlink_route_socket netlink_tcpdiag_socket netlink_nflog_socket netlink_xfrm_socket netlink_selinux_socket netlink_audit_socket netlink_dnrt_socket netlink_kobject_uevent_socket tun_socket netlink_iscsi_socket netlink_fib_lookup_socket netlink_connector_socket netlink_netfilter_socket netlink_generic_socket netlink_scsitransport_socket netlink_rdma_socket netlink_crypto_socket sctp_socket icmp_socket ax25_socket ipx_socket netrom_socket atmpvc_socket x25_socket rose_socket decnet_socket atmsvc_socket rds_socket irda_socket pppox_socket llc_socket can_socket tipc_socket bluetooth_socket iucv_socket rxrpc_socket isdn_socket phonet_socket ieee802154_socket caif_socket alg_socket nfc_socket vsock_socket kcm_socket qipcrtr_socket smc_socket xdp_socket }')
|
2005-06-02 14:31:31 +00:00
|
|
|
|
|
|
|
#
|
|
|
|
# Datagram socket classes.
|
2016-12-01 17:12:34 +00:00
|
|
|
#
|
2005-06-02 14:31:31 +00:00
|
|
|
define(`dgram_socket_class_set', `{ udp_socket unix_dgram_socket }')
|
|
|
|
|
|
|
|
#
|
|
|
|
# Stream socket classes.
|
|
|
|
#
|
2018-03-19 09:59:54 +00:00
|
|
|
define(`stream_socket_class_set', `{ tcp_socket unix_stream_socket sctp_socket }')
|
2005-06-02 14:31:31 +00:00
|
|
|
|
2016-12-02 15:16:45 +00:00
|
|
|
#
|
|
|
|
# Unprivileged socket classes (exclude rawip, netlink, packet).
|
|
|
|
#
|
2018-03-19 09:59:54 +00:00
|
|
|
define(`unpriv_socket_class_set', `{ tcp_socket udp_socket unix_stream_socket unix_dgram_socket sctp_socket }')
|
2005-06-02 14:31:31 +00:00
|
|
|
|
2016-12-02 15:20:26 +00:00
|
|
|
|
2005-06-02 14:31:31 +00:00
|
|
|
########################################
|
2016-12-01 17:12:34 +00:00
|
|
|
#
|
2005-06-02 14:31:31 +00:00
|
|
|
# Macros for sets of permissions
|
|
|
|
#
|
|
|
|
|
|
|
|
#
|
|
|
|
# Permissions to mount and unmount file systems.
|
|
|
|
#
|
|
|
|
define(`mount_fs_perms', `{ mount remount unmount getattr }')
|
|
|
|
|
|
|
|
#
|
|
|
|
# Permissions for using sockets.
|
2016-12-01 17:12:34 +00:00
|
|
|
#
|
2005-06-02 14:31:31 +00:00
|
|
|
define(`rw_socket_perms', `{ ioctl read getattr write setattr append bind connect getopt setopt shutdown }')
|
|
|
|
|
|
|
|
#
|
|
|
|
# Permissions for creating and using sockets.
|
2016-12-01 17:12:34 +00:00
|
|
|
#
|
2005-06-02 14:31:31 +00:00
|
|
|
define(`create_socket_perms', `{ create rw_socket_perms }')
|
|
|
|
|
|
|
|
#
|
|
|
|
# Permissions for using stream sockets.
|
2016-12-01 17:12:34 +00:00
|
|
|
#
|
2005-06-02 14:31:31 +00:00
|
|
|
define(`rw_stream_socket_perms', `{ rw_socket_perms listen accept }')
|
|
|
|
|
|
|
|
#
|
|
|
|
# Permissions for creating and using stream sockets.
|
2016-12-01 17:12:34 +00:00
|
|
|
#
|
2005-06-02 14:31:31 +00:00
|
|
|
define(`create_stream_socket_perms', `{ create_socket_perms listen accept }')
|
|
|
|
|
|
|
|
#
|
|
|
|
# Permissions for creating and using sockets.
|
2016-12-01 17:12:34 +00:00
|
|
|
#
|
2005-06-02 14:31:31 +00:00
|
|
|
define(`connected_socket_perms', `{ create ioctl read getattr write setattr append bind getopt setopt shutdown }')
|
|
|
|
|
|
|
|
#
|
|
|
|
# Permissions for creating and using sockets.
|
2016-12-01 17:12:34 +00:00
|
|
|
#
|
2005-06-02 14:31:31 +00:00
|
|
|
define(`connected_stream_socket_perms', `{ connected_socket_perms listen accept }')
|
|
|
|
|
|
|
|
#
|
|
|
|
# Permissions for creating and using netlink sockets.
|
2016-12-01 17:12:34 +00:00
|
|
|
#
|
2005-06-02 14:31:31 +00:00
|
|
|
define(`create_netlink_socket_perms', `{ create_socket_perms nlmsg_read nlmsg_write }')
|
|
|
|
|
|
|
|
#
|
|
|
|
# Permissions for using netlink sockets for operations that modify state.
|
2016-12-01 17:12:34 +00:00
|
|
|
#
|
2005-06-02 14:31:31 +00:00
|
|
|
define(`rw_netlink_socket_perms', `{ create_socket_perms nlmsg_read nlmsg_write }')
|
|
|
|
|
|
|
|
#
|
|
|
|
# Permissions for using netlink sockets for operations that observe state.
|
2016-12-01 17:12:34 +00:00
|
|
|
#
|
2005-06-02 14:31:31 +00:00
|
|
|
define(`r_netlink_socket_perms', `{ create_socket_perms nlmsg_read }')
|
|
|
|
|
|
|
|
#
|
|
|
|
# Permissions for sending all signals.
|
|
|
|
#
|
|
|
|
define(`signal_perms', `{ sigchld sigkill sigstop signull signal }')
|
|
|
|
|
|
|
|
#
|
|
|
|
# Permissions for using System V IPC
|
|
|
|
#
|
|
|
|
define(`r_sem_perms', `{ associate getattr read unix_read }')
|
2016-12-01 17:12:34 +00:00
|
|
|
define(`rw_sem_perms', `{ r_sem_perms unix_write write }')
|
|
|
|
define(`create_sem_perms', `{ create destroy rw_sem_perms setattr }')
|
2005-06-02 14:31:31 +00:00
|
|
|
define(`r_msgq_perms', `{ associate getattr read unix_read }')
|
2016-12-01 17:12:34 +00:00
|
|
|
define(`rw_msgq_perms', `{ enqueue r_msgq_perms unix_write write }')
|
|
|
|
define(`create_msgq_perms', `{ create destroy rw_msgq_perms setattr }')
|
2005-06-02 14:31:31 +00:00
|
|
|
define(`r_shm_perms', `{ associate getattr read unix_read }')
|
2016-12-01 17:12:34 +00:00
|
|
|
define(`rw_shm_perms', `{ lock r_shm_perms unix_write write }')
|
|
|
|
define(`create_shm_perms', `{ create destroy lock rw_shm_perms setattr }')
|
2005-10-12 18:17:10 +00:00
|
|
|
|
|
|
|
#
|
2006-12-12 20:08:08 +00:00
|
|
|
# Directory (dir)
|
2005-10-12 18:17:10 +00:00
|
|
|
#
|
|
|
|
define(`getattr_dir_perms',`{ getattr }')
|
|
|
|
define(`setattr_dir_perms',`{ setattr }')
|
2009-10-22 13:13:04 +00:00
|
|
|
define(`search_dir_perms',`{ getattr search open }')
|
2008-10-16 16:09:20 +00:00
|
|
|
define(`list_dir_perms',`{ getattr search open read lock ioctl }')
|
|
|
|
define(`add_entry_dir_perms',`{ getattr search open lock ioctl write add_name }')
|
|
|
|
define(`del_entry_dir_perms',`{ getattr search open lock ioctl write remove_name }')
|
|
|
|
define(`rw_dir_perms', `{ open read getattr lock search ioctl add_name remove_name write }')
|
2006-12-12 20:08:08 +00:00
|
|
|
define(`create_dir_perms',`{ getattr create }')
|
2007-05-03 13:15:48 +00:00
|
|
|
define(`rename_dir_perms',`{ getattr rename }')
|
2006-12-12 20:08:08 +00:00
|
|
|
define(`delete_dir_perms',`{ getattr rmdir }')
|
2008-05-23 18:22:57 +00:00
|
|
|
define(`manage_dir_perms',`{ create open getattr setattr read write link unlink rename search add_name remove_name reparent rmdir lock ioctl }')
|
2006-12-12 20:08:08 +00:00
|
|
|
define(`relabelfrom_dir_perms',`{ getattr relabelfrom }')
|
|
|
|
define(`relabelto_dir_perms',`{ getattr relabelto }')
|
|
|
|
define(`relabel_dir_perms',`{ getattr relabelfrom relabelto }')
|
2005-10-12 18:17:10 +00:00
|
|
|
|
|
|
|
#
|
2006-12-12 20:08:08 +00:00
|
|
|
# Regular file (file)
|
2005-06-17 18:56:23 +00:00
|
|
|
#
|
2005-10-12 18:17:10 +00:00
|
|
|
define(`getattr_file_perms',`{ getattr }')
|
|
|
|
define(`setattr_file_perms',`{ setattr }')
|
2020-07-29 18:29:16 +00:00
|
|
|
define(`read_inherited_file_perms',`{ getattr read lock ioctl }')
|
2008-10-16 16:09:20 +00:00
|
|
|
define(`read_file_perms',`{ getattr open read lock ioctl }')
|
2017-12-13 23:58:34 +00:00
|
|
|
define(`mmap_read_inherited_file_perms',`{ getattr map read ioctl }')
|
|
|
|
define(`mmap_read_file_perms',`{ getattr open map read ioctl }')
|
|
|
|
define(`mmap_exec_inherited_file_perms',`{ getattr map read execute ioctl }')
|
|
|
|
define(`mmap_exec_file_perms',`{ getattr open map read execute ioctl }')
|
2017-05-24 19:40:18 +00:00
|
|
|
define(`exec_file_perms',`{ getattr open map read execute ioctl execute_no_trans }')
|
2008-10-16 16:09:20 +00:00
|
|
|
define(`append_file_perms',`{ getattr open append lock ioctl }')
|
2017-12-08 12:43:47 +00:00
|
|
|
define(`write_inherited_file_perms',`{ getattr write append lock ioctl }')
|
2008-10-16 16:09:20 +00:00
|
|
|
define(`write_file_perms',`{ getattr open write append lock ioctl }')
|
2017-02-23 04:14:16 +00:00
|
|
|
define(`rw_inherited_file_perms',`{ getattr read write append ioctl lock }')
|
|
|
|
define(`rw_file_perms',`{ open rw_inherited_file_perms }')
|
2017-12-13 23:58:34 +00:00
|
|
|
define(`mmap_rw_inherited_file_perms',`{ getattr map read write ioctl }')
|
|
|
|
define(`mmap_rw_file_perms',`{ getattr open map read write ioctl }')
|
2008-05-23 18:22:57 +00:00
|
|
|
define(`create_file_perms',`{ getattr create open }')
|
2006-12-12 20:08:08 +00:00
|
|
|
define(`rename_file_perms',`{ getattr rename }')
|
2006-03-02 23:41:11 +00:00
|
|
|
define(`delete_file_perms',`{ getattr unlink }')
|
2008-05-23 18:22:57 +00:00
|
|
|
define(`manage_file_perms',`{ create open getattr setattr read write append rename link unlink ioctl lock }')
|
2006-12-12 20:08:08 +00:00
|
|
|
define(`relabelfrom_file_perms',`{ getattr relabelfrom }')
|
|
|
|
define(`relabelto_file_perms',`{ getattr relabelto }')
|
|
|
|
define(`relabel_file_perms',`{ getattr relabelfrom relabelto }')
|
|
|
|
|
|
|
|
#
|
|
|
|
# Symbolic link (lnk_file)
|
|
|
|
#
|
|
|
|
define(`getattr_lnk_file_perms',`{ getattr }')
|
|
|
|
define(`setattr_lnk_file_perms',`{ setattr }')
|
|
|
|
define(`read_lnk_file_perms',`{ getattr read }')
|
2008-05-22 15:24:52 +00:00
|
|
|
define(`append_lnk_file_perms',`{ getattr append lock ioctl }')
|
|
|
|
define(`write_lnk_file_perms',`{ getattr append write lock ioctl }')
|
2006-12-12 20:08:08 +00:00
|
|
|
define(`rw_lnk_file_perms',`{ getattr read write lock ioctl }')
|
|
|
|
define(`create_lnk_file_perms',`{ create getattr }')
|
|
|
|
define(`rename_lnk_file_perms',`{ getattr rename }')
|
|
|
|
define(`delete_lnk_file_perms',`{ getattr unlink }')
|
2014-08-23 11:35:50 +00:00
|
|
|
define(`manage_lnk_file_perms',`{ create read write getattr setattr link unlink rename ioctl lock }')
|
2006-12-12 20:08:08 +00:00
|
|
|
define(`relabelfrom_lnk_file_perms',`{ getattr relabelfrom }')
|
|
|
|
define(`relabelto_lnk_file_perms',`{ getattr relabelto }')
|
|
|
|
define(`relabel_lnk_file_perms',`{ getattr relabelfrom relabelto }')
|
|
|
|
|
|
|
|
#
|
|
|
|
# (Un)named Pipes/FIFOs (fifo_file)
|
|
|
|
#
|
|
|
|
define(`getattr_fifo_file_perms',`{ getattr }')
|
|
|
|
define(`setattr_fifo_file_perms',`{ setattr }')
|
2008-10-16 16:09:20 +00:00
|
|
|
define(`read_fifo_file_perms',`{ getattr open read lock ioctl }')
|
|
|
|
define(`append_fifo_file_perms',`{ getattr open append lock ioctl }')
|
|
|
|
define(`write_fifo_file_perms',`{ getattr open write append lock ioctl }')
|
2017-02-12 11:18:15 +00:00
|
|
|
define(`rw_inherited_fifo_file_perms',`{ getattr read write append ioctl lock }')
|
|
|
|
define(`rw_fifo_file_perms',`{ open rw_inherited_fifo_file_perms }')
|
2008-05-23 18:22:57 +00:00
|
|
|
define(`create_fifo_file_perms',`{ getattr create open }')
|
2007-07-31 15:11:22 +00:00
|
|
|
define(`rename_fifo_file_perms',`{ getattr rename }')
|
2006-12-12 20:08:08 +00:00
|
|
|
define(`delete_fifo_file_perms',`{ getattr unlink }')
|
2008-05-23 18:22:57 +00:00
|
|
|
define(`manage_fifo_file_perms',`{ create open getattr setattr read write append rename link unlink ioctl lock }')
|
2006-12-12 20:08:08 +00:00
|
|
|
define(`relabelfrom_fifo_file_perms',`{ getattr relabelfrom }')
|
|
|
|
define(`relabelto_fifo_file_perms',`{ getattr relabelto }')
|
|
|
|
define(`relabel_fifo_file_perms',`{ getattr relabelfrom relabelto }')
|
|
|
|
|
|
|
|
#
|
|
|
|
# (Un)named Sockets (sock_file)
|
|
|
|
#
|
|
|
|
define(`getattr_sock_file_perms',`{ getattr }')
|
|
|
|
define(`setattr_sock_file_perms',`{ setattr }')
|
2009-03-11 14:58:03 +00:00
|
|
|
define(`read_sock_file_perms',`{ getattr open read }')
|
|
|
|
define(`write_sock_file_perms',`{ getattr write open append }')
|
|
|
|
define(`rw_sock_file_perms',`{ getattr open read write append }')
|
|
|
|
define(`create_sock_file_perms',`{ getattr create open }')
|
2007-07-31 15:11:22 +00:00
|
|
|
define(`rename_sock_file_perms',`{ getattr rename }')
|
2006-12-12 20:08:08 +00:00
|
|
|
define(`delete_sock_file_perms',`{ getattr unlink }')
|
2009-03-11 14:58:03 +00:00
|
|
|
define(`manage_sock_file_perms',`{ create open getattr setattr read write rename link unlink ioctl lock append }')
|
2006-12-12 20:08:08 +00:00
|
|
|
define(`relabelfrom_sock_file_perms',`{ getattr relabelfrom }')
|
|
|
|
define(`relabelto_sock_file_perms',`{ getattr relabelto }')
|
|
|
|
define(`relabel_sock_file_perms',`{ getattr relabelfrom relabelto }')
|
|
|
|
|
|
|
|
#
|
|
|
|
# Block device nodes (blk_file)
|
|
|
|
#
|
|
|
|
define(`getattr_blk_file_perms',`{ getattr }')
|
|
|
|
define(`setattr_blk_file_perms',`{ setattr }')
|
2008-10-16 16:09:20 +00:00
|
|
|
define(`read_blk_file_perms',`{ getattr open read lock ioctl }')
|
|
|
|
define(`append_blk_file_perms',`{ getattr open append lock ioctl }')
|
|
|
|
define(`write_blk_file_perms',`{ getattr open write append lock ioctl }')
|
|
|
|
define(`rw_blk_file_perms',`{ getattr open read write append ioctl lock }')
|
2006-12-12 20:08:08 +00:00
|
|
|
define(`create_blk_file_perms',`{ getattr create }')
|
|
|
|
define(`rename_blk_file_perms',`{ getattr rename }')
|
|
|
|
define(`delete_blk_file_perms',`{ getattr unlink }')
|
2008-05-23 18:22:57 +00:00
|
|
|
define(`manage_blk_file_perms',`{ create open getattr setattr read write append rename link unlink ioctl lock }')
|
2006-12-12 20:08:08 +00:00
|
|
|
define(`relabelfrom_blk_file_perms',`{ getattr relabelfrom }')
|
|
|
|
define(`relabelto_blk_file_perms',`{ getattr relabelto }')
|
|
|
|
define(`relabel_blk_file_perms',`{ getattr relabelfrom relabelto }')
|
|
|
|
|
|
|
|
#
|
|
|
|
# Character device nodes (chr_file)
|
|
|
|
#
|
|
|
|
define(`getattr_chr_file_perms',`{ getattr }')
|
|
|
|
define(`setattr_chr_file_perms',`{ setattr }')
|
2008-10-16 16:09:20 +00:00
|
|
|
define(`read_chr_file_perms',`{ getattr open read lock ioctl }')
|
|
|
|
define(`append_chr_file_perms',`{ getattr open append lock ioctl }')
|
|
|
|
define(`write_chr_file_perms',`{ getattr open write append lock ioctl }')
|
|
|
|
define(`rw_chr_file_perms',`{ getattr open read write append ioctl lock }')
|
2006-12-12 20:08:08 +00:00
|
|
|
define(`create_chr_file_perms',`{ getattr create }')
|
|
|
|
define(`rename_chr_file_perms',`{ getattr rename }')
|
|
|
|
define(`delete_chr_file_perms',`{ getattr unlink }')
|
2008-05-23 18:22:57 +00:00
|
|
|
define(`manage_chr_file_perms',`{ create open getattr setattr read write append rename link unlink ioctl lock }')
|
2006-12-12 20:08:08 +00:00
|
|
|
define(`relabelfrom_chr_file_perms',`{ getattr relabelfrom }')
|
|
|
|
define(`relabelto_chr_file_perms',`{ getattr relabelto }')
|
|
|
|
define(`relabel_chr_file_perms',`{ getattr relabelfrom relabelto }')
|
|
|
|
|
2016-12-01 17:12:34 +00:00
|
|
|
|
2006-12-12 20:08:08 +00:00
|
|
|
########################################
|
|
|
|
#
|
|
|
|
# Special permission sets
|
|
|
|
#
|
2005-06-17 18:56:23 +00:00
|
|
|
|
|
|
|
#
|
|
|
|
# Use (read and write) terminals
|
|
|
|
#
|
2017-02-12 11:18:15 +00:00
|
|
|
define(`rw_inherited_term_perms', `{ getattr read write append ioctl }')
|
|
|
|
define(`rw_term_perms', `{ rw_inherited_term_perms open }')
|
2005-07-15 15:53:54 +00:00
|
|
|
|
2006-01-16 18:48:57 +00:00
|
|
|
#
|
|
|
|
# Sockets
|
|
|
|
#
|
|
|
|
define(`client_stream_socket_perms', `{ create ioctl read getattr write setattr append bind getopt setopt shutdown }')
|
|
|
|
define(`server_stream_socket_perms', `{ client_stream_socket_perms listen accept }')
|
2009-11-25 15:52:16 +00:00
|
|
|
|
|
|
|
#
|
|
|
|
# Keys
|
|
|
|
#
|
|
|
|
define(`manage_key_perms', `{ create link read search setattr view write } ')
|