diff --git a/include/minix/com.h b/include/minix/com.h index 7ff70e30c..b44dccffa 100644 --- a/include/minix/com.h +++ b/include/minix/com.h @@ -352,8 +352,10 @@ # define SYS_SCHEDCTL (KERNEL_CALL + 54) /* sys_schedctl() */ # define SYS_STATECTL (KERNEL_CALL + 55) /* sys_statectl() */ +# define SYS_SAFEMEMSET (KERNEL_CALL + 56) /* sys_safememset() */ + /* Total */ -#define NR_SYS_CALLS 56 /* number of kernel calls */ +#define NR_SYS_CALLS 57 /* number of kernel calls */ #define SYS_CALL_MASK_SIZE BITMAP_CHUNKS(NR_SYS_CALLS) @@ -361,7 +363,7 @@ #define SYS_BASIC_CALLS \ SYS_EXIT, SYS_SAFECOPYFROM, SYS_SAFECOPYTO, SYS_VSAFECOPY, SYS_GETINFO, \ SYS_TIMES, SYS_SETALARM, SYS_SETGRANT, SYS_SAFEMAP, SYS_SAFEREVMAP, \ - SYS_SAFEUNMAP, SYS_PROFBUF, SYS_SYSCTL, SYS_STATECTL + SYS_SAFEUNMAP, SYS_PROFBUF, SYS_SYSCTL, SYS_STATECTL, SYS_SAFEMEMSET /* Field names for SYS_MEMSET. */ #define MEM_PTR m2_p1 /* base */ @@ -561,6 +563,13 @@ #define SCP_ADDRESS m2_p1 /* my own address */ #define SCP_BYTES m2_l2 /* bytes from offset */ +/* SYS_SAFEMEMSET */ +#define SMS_DST m2_i1 /* dst endpoint */ +#define SMS_GID m2_i3 /* grant id */ +#define SMS_OFFSET m2_l1 /* offset within grant */ +#define SMS_BYTES m2_l2 /* bytes from offset */ +#define SMS_PATTERN m2_i2 /* memset() pattern */ + /* Field names for SYS_VSAFECOPY* */ #define VSCP_VEC_ADDR m2_p1 /* start of vector */ #define VSCP_VEC_SIZE m2_l2 /* elements in vector */ diff --git a/kernel/system.c b/kernel/system.c index e19d8f525..cb6ef14e8 100644 --- a/kernel/system.c +++ b/kernel/system.c @@ -226,6 +226,9 @@ void system_init(void) map(SYS_SAFECOPYTO, do_safecopy_to); /* copy with pre-granted permission */ map(SYS_VSAFECOPY, do_vsafecopy); /* vectored safecopy */ + /* safe memset */ + map(SYS_SAFEMEMSET, do_safememset); /* safememset */ + /* Mapping. */ map(SYS_SAFEMAP, do_safemap); /* map pages from other process */ map(SYS_SAFEREVMAP, do_saferevmap); /* grantor revokes the map grant */ diff --git a/kernel/system.h b/kernel/system.h index 19285a176..91a436848 100644 --- a/kernel/system.h +++ b/kernel/system.h @@ -178,6 +178,8 @@ int do_vmctl(struct proc * caller, message *m_ptr); int do_setgrant(struct proc * caller, message *m_ptr); int do_readbios(struct proc * caller, message *m_ptr); +int do_safememset(struct proc * caller, message *m_ptr); + int do_safemap(struct proc * caller, message *m_ptr); int do_saferevmap(struct proc * caller, message *m_ptr); int do_safeunmap(struct proc * caller, message *m_ptr); diff --git a/kernel/system/Makefile.inc b/kernel/system/Makefile.inc index c4ccc04ed..50f4e41b3 100644 --- a/kernel/system/Makefile.inc +++ b/kernel/system/Makefile.inc @@ -25,6 +25,7 @@ SRCS+= \ do_setgrant.c \ do_privctl.c \ do_safecopy.c \ + do_safememset.c \ do_safemap.c \ do_sysctl.c \ do_getksig.c \ diff --git a/kernel/system/do_safememset.c b/kernel/system/do_safememset.c new file mode 100644 index 000000000..cfccec996 --- /dev/null +++ b/kernel/system/do_safememset.c @@ -0,0 +1,58 @@ +/* The kernel call implemented in this file: + * m_type: SYS_SAFEMEMSET + * + * The parameters for this kernel call are: + * SMS_DST dst endpoint + * SMS_GID grant id + * SMS_OFFSET offset within grant + * SMS_PATTERN memset pattern byte + * SMS_BYTES bytes from offset + */ +#include + +#include + +#include "kernel/system.h" +#include "kernel.h" + +/*===========================================================================* + * do_safememset * + *===========================================================================*/ +int do_safememset(struct proc *caller, message *m_ptr) { + /* Implementation of the do_safememset() kernel call */ + + /* Extract parameters */ + endpoint_t dst_endpt = m_ptr->SMS_DST; + endpoint_t caller_endpt = caller->p_endpoint; + cp_grant_id_t grantid = m_ptr->SMS_GID; + vir_bytes g_offset = m_ptr->SMS_OFFSET; + int pattern = m_ptr->SMS_PATTERN; + size_t len = (size_t)m_ptr->SMS_BYTES; + + struct proc *dst_p; + endpoint_t new_granter; + static vir_bytes v_offset; + int r; + + if (dst_endpt == NONE || caller_endpt == NONE) + return EFAULT; + + if (!(dst_p = endpoint_lookup(dst_endpt))) + return EINVAL; + + if (!(priv(dst_p) && priv(dst_p)->s_grant_table)) { + printf("safememset: dst %d has no grant table\n", dst_endpt); + return EINVAL; + } + + /* Verify permission exists, memset always requires CPF_WRITE */ + r = verify_grant(dst_endpt, caller_endpt, grantid, len, CPF_WRITE, + g_offset, &v_offset, &new_granter); + + if (r != OK) { + printf("safememset: grant %d verify failed %d", grantid, r); + return r; + } + + return vm_memset(caller, new_granter, v_offset, pattern, len); +}