From 902e1df69542e07e7c363f5b599ac1551b8fbb64 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 20 Mar 2018 15:27:43 +0100 Subject: erts: Add dynamic loaded drivers to list of "taints" --- erts/emulator/beam/erl_bif_ddll.c | 9 +++++++++ erts/emulator/beam/erl_nif.c | 40 +++++++++++++++++++++++++------------ erts/emulator/beam/global.h | 1 + erts/emulator/test/driver_SUITE.erl | 12 ++++++++++- 4 files changed, 48 insertions(+), 14 deletions(-) (limited to 'erts/emulator') diff --git a/erts/emulator/beam/erl_bif_ddll.c b/erts/emulator/beam/erl_bif_ddll.c index 579e9b12f4..8220ba97a2 100644 --- a/erts/emulator/beam/erl_bif_ddll.c +++ b/erts/emulator/beam/erl_bif_ddll.c @@ -1505,6 +1505,15 @@ static int do_load_driver_entry(DE_Handle *dh, char *path, char *name) res = ERL_DE_LOAD_ERROR_BAD_NAME; goto error; } + + { + Eterm name_atom = erts_atom_put((byte*)name, sys_strlen(name), + ERTS_ATOM_ENC_LATIN1, 0); + if (is_non_value(name_atom)) + goto error; + erts_add_taint(name_atom); + } + erts_atomic_init_nob(&(dh->refc), (erts_aint_t) 0); erts_atomic32_init_nob(&dh->port_count, 0); dh->full_path = erts_alloc(ERTS_ALC_T_DDLL_HANDLE, sys_strlen(path) + 1); diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index c60cc7fecf..121a7d943f 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -3726,16 +3726,26 @@ static Eterm mkatom(const char *str) return am_atom_put(str, sys_strlen(str)); } -static struct tainted_module_t +struct tainted_module_t { struct tainted_module_t* next; Eterm module_atom; -}*first_tainted_module = NULL; +}; + +erts_atomic_t first_taint; /* struct tainted_module_t* */ -static void add_taint(Eterm mod_atom) +void erts_add_taint(Eterm mod_atom) { - struct tainted_module_t* t; - for (t=first_tainted_module ; t!=NULL; t=t->next) { +#ifdef ERTS_ENABLE_LOCK_CHECK + extern erts_rwmtx_t erts_driver_list_lock; /* Mutex for driver list */ +#endif + struct tainted_module_t *first, *t; + + ERTS_LC_ASSERT(erts_lc_rwmtx_is_rwlocked(&erts_driver_list_lock) + || erts_thr_progress_is_blocking()); + + first = (struct tainted_module_t*) erts_atomic_read_nob(&first_taint); + for (t=first ; t; t=t->next) { if (t->module_atom == mod_atom) { return; } @@ -3743,22 +3753,24 @@ static void add_taint(Eterm mod_atom) t = erts_alloc_fnf(ERTS_ALC_T_TAINT, sizeof(*t)); if (t != NULL) { t->module_atom = mod_atom; - t->next = first_tainted_module; - first_tainted_module = t; + t->next = first; + erts_atomic_set_nob(&first_taint, (erts_aint_t)t); } } Eterm erts_nif_taints(Process* p) { - struct tainted_module_t* t; + struct tainted_module_t *first, *t; unsigned cnt = 0; Eterm list = NIL; Eterm* hp; - for (t=first_tainted_module ; t!=NULL; t=t->next) { + + first = (struct tainted_module_t*) erts_atomic_read_nob(&first_taint); + for (t=first ; t!=NULL; t=t->next) { cnt++; } hp = HAlloc(p,cnt*2); - for (t=first_tainted_module ; t!=NULL; t=t->next) { + for (t=first ; t!=NULL; t=t->next) { list = CONS(hp, t->module_atom, list); hp += 2; } @@ -3767,9 +3779,11 @@ Eterm erts_nif_taints(Process* p) void erts_print_nif_taints(fmtfn_t to, void* to_arg) { - struct tainted_module_t* t; + struct tainted_module_t *t; const char* delim = ""; - for (t=first_tainted_module ; t!=NULL; t=t->next) { + + t = (struct tainted_module_t*) erts_atomic_read_nob(&first_taint); + for ( ; t; t = t->next) { const Atom* atom = atom_tab(atom_val(t->module_atom)); erts_cbprintf(to,to_arg,"%s%.*s", delim, atom->len, atom->name); delim = ","; @@ -3964,7 +3978,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) " function: '%s'", errdesc.str); } - else if ((add_taint(mod_atom), + else if ((erts_add_taint(mod_atom), (entry = erts_sys_ddll_call_nif_init(init_func)) == NULL)) { ret = load_nif_error(BIF_P, bad_lib, "Library init-call unsuccessful"); } diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index 0f23027752..3c98ccfef3 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -117,6 +117,7 @@ extern void erts_pre_nif(struct enif_environment_t*, Process*, extern void erts_post_nif(struct enif_environment_t* env); extern void erts_resource_stop(ErtsResource*, ErlNifEvent, int is_direct_call); void erts_fire_nif_monitor(ErtsResource*, Eterm pid, Eterm ref); +extern void erts_add_taint(Eterm mod_atom); extern Eterm erts_nif_taints(Process* p); extern void erts_print_nif_taints(fmtfn_t to, void* to_arg); void erts_unload_nif(struct erl_module_nif* nif); diff --git a/erts/emulator/test/driver_SUITE.erl b/erts/emulator/test/driver_SUITE.erl index 294c42780d..40c7cc11e1 100644 --- a/erts/emulator/test/driver_SUITE.erl +++ b/erts/emulator/test/driver_SUITE.erl @@ -2589,8 +2589,18 @@ stop_driver(Port, Name) -> ok = erl_ddll:stop(). load_driver(Dir, Driver) -> + Before = erlang:system_info(taints), case erl_ddll:load_driver(Dir, Driver) of - ok -> ok; + ok -> + After = erlang:system_info(taints), + case lists:member(Driver, Before) of + true -> + After = Before; + false -> + true = lists:member(Driver, After), + Before = lists:delete(Driver, After) + end, + ok; {error, Error} = Res -> io:format("~s\n", [erl_ddll:format_error(Error)]), Res -- cgit v1.2.3 From 5b557bccac579291301a7a4d78a3d992b4e9373d Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 20 Mar 2018 18:55:51 +0100 Subject: erts: Refactor erts_static_nif_get_nif_init to return pointer to ErtsStaticNifEntry. --- erts/emulator/beam/erl_nif.c | 12 ++++++++---- erts/emulator/beam/global.h | 6 +++++- erts/emulator/utils/make_driver_tab | 15 +++------------ 3 files changed, 16 insertions(+), 17 deletions(-) (limited to 'erts/emulator') diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index 121a7d943f..0720796b53 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -3938,10 +3938,14 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) ASSERT(module_p != NULL); mod_atomp = atom_tab(atom_val(mod_atom)); - init_func = erts_static_nif_get_nif_init((char*)mod_atomp->name, mod_atomp->len); - if (init_func != NULL) - handle = init_func; - + { + ErtsStaticNifEntry* sne; + sne = erts_static_nif_get_nif_init((char*)mod_atomp->name, mod_atomp->len); + if (sne != NULL) { + init_func = sne->nif_init; + handle = init_func; + } + } this_mi = &module_p->curr; prev_mi = &module_p->old; if (in_area(caller, module_p->old.code_hdr, module_p->old.code_length)) { diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index 3c98ccfef3..ae9fe0cc62 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -1178,7 +1178,11 @@ void erts_lcnt_update_port_locks(int enable); /* driver_tab.c */ typedef void *(*ErtsStaticNifInitFPtr)(void); -ErtsStaticNifInitFPtr erts_static_nif_get_nif_init(const char *name, int len); +typedef struct ErtsStaticNifEntry_ { + const char *nif_name; + ErtsStaticNifInitFPtr nif_init; +} ErtsStaticNifEntry; +ErtsStaticNifEntry* erts_static_nif_get_nif_init(const char *name, int len); int erts_is_static_nif(void *handle); void erts_init_static_drivers(void); diff --git a/erts/emulator/utils/make_driver_tab b/erts/emulator/utils/make_driver_tab index ffb5f58ebf..6f28a21f81 100755 --- a/erts/emulator/utils/make_driver_tab +++ b/erts/emulator/utils/make_driver_tab @@ -115,15 +115,6 @@ foreach (@static_drivers) { print "}\n"; -print <nif_name != NULL; p++) if (strncmp(p->nif_name, name, len) == 0 && p->nif_name[len] == 0) - return p->nif_init; + return p; return NULL; } -- cgit v1.2.3 From 8fea289244d8758c69b8c8443679b2d73cb2f70d Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 20 Mar 2018 19:24:42 +0100 Subject: erts: Remove our own NIF modules from "taints" Dynamic NIF libs and those added with config option --enable-static-nifs are considered as taints. --- erts/emulator/beam/erl_nif.c | 4 +++- erts/emulator/beam/global.h | 1 + erts/emulator/utils/make_driver_tab | 15 +++++++++++++-- 3 files changed, 17 insertions(+), 3 deletions(-) (limited to 'erts/emulator') diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index 0720796b53..8dcecd79f0 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -3892,6 +3892,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) ErtsSysDdllError errdesc = ERTS_SYS_DDLL_ERROR_INIT; Eterm ret = am_ok; int veto; + int taint = 1; struct erl_module_nif* lib = NULL; struct erl_module_instance* this_mi; struct erl_module_instance* prev_mi; @@ -3944,6 +3945,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) if (sne != NULL) { init_func = sne->nif_init; handle = init_func; + taint = sne->taint; } } this_mi = &module_p->curr; @@ -3982,7 +3984,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) " function: '%s'", errdesc.str); } - else if ((erts_add_taint(mod_atom), + else if ((taint ? erts_add_taint(mod_atom) : 0, (entry = erts_sys_ddll_call_nif_init(init_func)) == NULL)) { ret = load_nif_error(BIF_P, bad_lib, "Library init-call unsuccessful"); } diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index ae9fe0cc62..8a746ea4b1 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -1181,6 +1181,7 @@ typedef void *(*ErtsStaticNifInitFPtr)(void); typedef struct ErtsStaticNifEntry_ { const char *nif_name; ErtsStaticNifInitFPtr nif_init; + int taint; } ErtsStaticNifEntry; ErtsStaticNifEntry* erts_static_nif_get_nif_init(const char *name, int len); int erts_is_static_nif(void *handle); diff --git a/erts/emulator/utils/make_driver_tab b/erts/emulator/utils/make_driver_tab index 6f28a21f81..cefb3e2504 100755 --- a/erts/emulator/utils/make_driver_tab +++ b/erts/emulator/utils/make_driver_tab @@ -30,6 +30,7 @@ use File::Basename; my $file = ""; my $nif = ""; my @emu_drivers = (); +my @emu_nifs = (); my @static_drivers = (); my @static_nifs = (); my $mode = 1; @@ -61,7 +62,7 @@ while (@ARGV) { } elsif ($mode == 2) { $d = basename $d; $d =~ s/_nif(\..*|)$//; # strip nif.* or just nif - push(@static_nifs, $d); + push(@emu_nifs, $d); next; } $d = basename $d; @@ -116,6 +117,11 @@ foreach (@static_drivers) { print "}\n"; # prototypes +foreach (@emu_nifs) { + my $d = ${_}; + $d =~ s/\.debug//; # strip .debug + print "void *".$d."_nif_init(void);\n"; +} foreach (@static_nifs) { my $d = ${_}; $d =~ s/\.debug//; # strip .debug @@ -125,10 +131,15 @@ foreach (@static_nifs) { # The array itself print "static ErtsStaticNifEntry static_nif_tab[] =\n{\n"; +foreach (@emu_nifs) { + my $d = ${_}; + $d =~ s/\.debug//; # strip .debug + print " {\"${_}\", &".$d."_nif_init, 0},\n"; +} foreach (@static_nifs) { my $d = ${_}; $d =~ s/\.debug//; # strip .debug - print " {\"${_}\",&".$d."_nif_init},\n"; + print " {\"${_}\", &".$d."_nif_init, 1},\n"; } print " {NULL,NULL}\n};\n"; -- cgit v1.2.3 From b48df378266717e1f6b79b96eb0f69cb08081585 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 26 Mar 2018 15:45:05 +0200 Subject: erts: Fix harmless bug in macro IS_DRIVER_VERSION_GE harmless until we bump major version --- erts/emulator/beam/io.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'erts/emulator') diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c index e4a5f2b6b6..410fe89b02 100644 --- a/erts/emulator/beam/io.c +++ b/erts/emulator/beam/io.c @@ -7613,7 +7613,8 @@ no_stop_select_callback(ErlDrvEvent event, void* private) } #define IS_DRIVER_VERSION_GE(DE,MAJOR,MINOR) \ - ((DE)->major_version >= (MAJOR) && (DE)->minor_version >= (MINOR)) + ((DE)->major_version > (MAJOR) || \ + ((DE)->major_version == (MAJOR) && (DE)->minor_version >= (MINOR))) static int init_driver(erts_driver_t *drv, ErlDrvEntry *de, DE_Handle *handle) -- cgit v1.2.3 From 39cf4e75f31e9abe46c9fe39000368c1243fdcf3 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 26 Mar 2018 15:48:12 +0200 Subject: erts: Include foreign static linked drivers in taints That is, driver added with config option --enable-static-drivers. --- erts/emulator/beam/erl_bif_ddll.c | 10 +--------- erts/emulator/beam/global.h | 6 +++++- erts/emulator/beam/io.c | 33 +++++++++++++++++++++++---------- erts/emulator/utils/make_driver_tab | 10 +++++----- 4 files changed, 34 insertions(+), 25 deletions(-) (limited to 'erts/emulator') diff --git a/erts/emulator/beam/erl_bif_ddll.c b/erts/emulator/beam/erl_bif_ddll.c index 8220ba97a2..294bce115f 100644 --- a/erts/emulator/beam/erl_bif_ddll.c +++ b/erts/emulator/beam/erl_bif_ddll.c @@ -1506,14 +1506,6 @@ static int do_load_driver_entry(DE_Handle *dh, char *path, char *name) goto error; } - { - Eterm name_atom = erts_atom_put((byte*)name, sys_strlen(name), - ERTS_ATOM_ENC_LATIN1, 0); - if (is_non_value(name_atom)) - goto error; - erts_add_taint(name_atom); - } - erts_atomic_init_nob(&(dh->refc), (erts_aint_t) 0); erts_atomic32_init_nob(&dh->port_count, 0); dh->full_path = erts_alloc(ERTS_ALC_T_DDLL_HANDLE, sys_strlen(path) + 1); @@ -1521,7 +1513,7 @@ static int do_load_driver_entry(DE_Handle *dh, char *path, char *name) dh->flags = 0; dh->status = ERL_DE_OK; - if (erts_add_driver_entry(dp, dh, 1) != 0 /* io.c */) { + if (erts_add_driver_entry(dp, dh, 1, 1) != 0 /* io.c */) { /* * The init in the driver struct did not return 0 */ diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index 8a746ea4b1..c8354f9fcf 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -1152,7 +1152,7 @@ typedef struct { #define ERTS_SPAWN_DRIVER 1 #define ERTS_SPAWN_EXECUTABLE 2 #define ERTS_SPAWN_ANY (ERTS_SPAWN_DRIVER | ERTS_SPAWN_EXECUTABLE) -int erts_add_driver_entry(ErlDrvEntry *drv, DE_Handle *handle, int driver_list_locked); +int erts_add_driver_entry(ErlDrvEntry *drv, DE_Handle *handle, int driver_list_locked, int taint); void erts_destroy_driver(erts_driver_t *drv); int erts_save_suspend_process_on_port(Port*, Process*); Port *erts_open_driver(erts_driver_t*, Eterm, char*, SysDriverOpts*, int *, int *); @@ -1177,6 +1177,10 @@ void erts_lcnt_update_port_locks(int enable); #endif /* driver_tab.c */ +typedef struct { + ErlDrvEntry* de; + int taint; +} ErtsStaticDriver; typedef void *(*ErtsStaticNifInitFPtr)(void); typedef struct ErtsStaticNifEntry_ { const char *nif_name; diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c index 410fe89b02..5d9d7b6ed7 100644 --- a/erts/emulator/beam/io.c +++ b/erts/emulator/beam/io.c @@ -60,7 +60,7 @@ extern ErlDrvEntry spawn_driver_entry; #ifndef __WIN32__ extern ErlDrvEntry forker_driver_entry; #endif -extern ErlDrvEntry *driver_tab[]; /* table of static drivers, only used during initialization */ +extern ErtsStaticDriver driver_tab[]; /* table of static drivers, only used during initialization */ erts_driver_t *driver_list; /* List of all drivers, static and dynamic. */ erts_rwmtx_t erts_driver_list_lock; /* Mutex for driver list */ @@ -2964,7 +2964,7 @@ void erts_init_io(int port_tab_size, int port_tab_size_ignore_files, int legacy_port_tab) { - ErlDrvEntry** dp; + ErtsStaticDriver* dp; UWord common_element_size; erts_rwmtx_opt_t drv_list_rwmtx_opts = ERTS_RWMTX_OPT_DEFAULT_INITER; drv_list_rwmtx_opts.type = ERTS_RWMTX_TYPE_EXTREMELY_FREQUENT_READ; @@ -3023,8 +3023,8 @@ void erts_init_io(int port_tab_size, init_driver(&forker_driver, &forker_driver_entry, NULL); #endif erts_init_static_drivers(); - for (dp = driver_tab; *dp != NULL; dp++) - erts_add_driver_entry(*dp, NULL, 1); + for (dp = driver_tab; dp->de != NULL; dp++) + erts_add_driver_entry(dp->de, NULL, 1, dp->taint); erts_tsd_set(driver_list_lock_status_key, NULL); erts_rwmtx_rwunlock(&erts_driver_list_lock); @@ -7697,13 +7697,14 @@ void add_driver_entry(ErlDrvEntry *drv){ * Ignore result of erts_add_driver_entry, the init is not * allowed to fail when drivers are added by drivers. */ - erts_add_driver_entry(drv, NULL, rec_lock != NULL); + erts_add_driver_entry(drv, NULL, rec_lock != NULL, 0); } -int erts_add_driver_entry(ErlDrvEntry *de, DE_Handle *handle, int driver_list_locked) +int erts_add_driver_entry(ErlDrvEntry *de, DE_Handle *handle, + int driver_list_locked, int taint) { erts_driver_t *dp = erts_alloc(ERTS_ALC_T_DRIVER, sizeof(erts_driver_t)); - int res; + int err = 0; if (!driver_list_locked) { erts_rwmtx_rwlock(&erts_driver_list_lock); @@ -7720,9 +7721,21 @@ int erts_add_driver_entry(ErlDrvEntry *de, DE_Handle *handle, int driver_list_lo erts_tsd_set(driver_list_lock_status_key, (void *) 1); } - res = init_driver(dp, de, handle); + if (taint) { + Eterm name_atom = erts_atom_put((byte*)de->driver_name, + sys_strlen(de->driver_name), + ERTS_ATOM_ENC_LATIN1, 0); + if (is_atom(name_atom)) + erts_add_taint(name_atom); + else + err = 1; + } + + if (!err) { + err = init_driver(dp, de, handle); + } - if (res != 0) { + if (err) { /* * Remove it all again... */ @@ -7737,7 +7750,7 @@ int erts_add_driver_entry(ErlDrvEntry *de, DE_Handle *handle, int driver_list_lo erts_tsd_set(driver_list_lock_status_key, NULL); erts_rwmtx_rwunlock(&erts_driver_list_lock); } - return res; + return err; } /* Not allowed for dynamic drivers */ diff --git a/erts/emulator/utils/make_driver_tab b/erts/emulator/utils/make_driver_tab index cefb3e2504..b7bca1dc3a 100755 --- a/erts/emulator/utils/make_driver_tab +++ b/erts/emulator/utils/make_driver_tab @@ -95,22 +95,22 @@ foreach (@static_drivers) { } # The array itself -print "\nErlDrvEntry *driver_tab[] =\n{\n"; +print "\nErtsStaticDriver driver_tab[] =\n{\n"; foreach (@emu_drivers) { - print " &${_}driver_entry,\n"; + print " {&${_}driver_entry, 0},\n"; } foreach (@static_drivers) { - print " NULL, /* ${_} */\n"; + print " {NULL, 1}, /* ${_} */\n"; } -print " NULL\n};\n"; +print " {NULL}\n};\n"; print "void erts_init_static_drivers() {\n"; my $index = 0; foreach (@static_drivers) { - print " driver_tab[".(scalar @emu_drivers+$index)."] = ${_}_driver_init();\n"; + print " driver_tab[".(scalar @emu_drivers+$index)."].de = ${_}_driver_init();\n"; $index++; } -- cgit v1.2.3