diff --git a/SOURCES/rhbz1020207.patch b/SOURCES/rhbz1020207.patch new file mode 100644 index 0000000..54489d3 --- /dev/null +++ b/SOURCES/rhbz1020207.patch @@ -0,0 +1,87 @@ +From 9b1d74f9a9d606f1e483690afae0a4a8207c76db Mon Sep 17 00:00:00 2001 +From: David Smith +Date: Fri, 7 Feb 2014 10:27:14 -0600 +Subject: [PATCH] Remove the transport's unused "dropped" file. + +* runtime/transport/relay_v2.c: Unless _STP_USE_DROPPED_FILE is defined, + don't bother creating the unused "dropped" file. +--- + runtime/transport/relay_v2.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/runtime/transport/relay_v2.c b/runtime/transport/relay_v2.c +index 6c9815d..97e02f9 100644 +--- a/runtime/transport/relay_v2.c ++++ b/runtime/transport/relay_v2.c +@@ -43,8 +43,10 @@ + struct _stp_relay_data_type { + struct rchan *rchan; + atomic_t /* enum _stp_transport_state */ transport_state; ++#ifdef _STP_USE_DROPPED_FILE + struct dentry *dropped_file; + atomic_t dropped; ++#endif + atomic_t wakeup; + struct timer_list timer; + int overwrite_flag; +@@ -160,6 +162,7 @@ static void _stp_transport_data_fs_overwrite(int overwrite) + _stp_relay_data.overwrite_flag = overwrite; + } + ++#ifdef _STP_USE_DROPPED_FILE + static int __stp_relay_dropped_open(struct inode *inode, struct file *filp) + { + return 0; +@@ -181,6 +184,7 @@ static struct file_operations __stp_relay_dropped_fops = { + .open = __stp_relay_dropped_open, + .read = __stp_relay_dropped_read, + }; ++#endif + + /* + * Keep track of how many times we encountered a full subbuffer, to aid +@@ -193,7 +197,9 @@ static int __stp_relay_subbuf_start_callback(struct rchan_buf *buf, + if (_stp_relay_data.overwrite_flag || !relay_buf_full(buf)) + return 1; + ++#ifdef _STP_USE_DROPPED_FILE + atomic_inc(&_stp_relay_data.dropped); ++#endif + return 0; + } + +@@ -270,8 +276,10 @@ static void _stp_transport_data_fs_stop(void) + static void _stp_transport_data_fs_close(void) + { + _stp_transport_data_fs_stop(); ++#ifdef _STP_USE_DROPPED_FILE + if (_stp_relay_data.dropped_file) + debugfs_remove(_stp_relay_data.dropped_file); ++#endif + if (_stp_relay_data.rchan) { + relay_close(_stp_relay_data.rchan); + _stp_relay_data.rchan = NULL; +@@ -286,9 +294,11 @@ static int _stp_transport_data_fs_init(void) + + atomic_set(&_stp_relay_data.transport_state, STP_TRANSPORT_STOPPED); + _stp_relay_data.overwrite_flag = 0; ++ _stp_relay_data.rchan = NULL; ++ ++#ifdef _STP_USE_DROPPED_FILE + atomic_set(&_stp_relay_data.dropped, 0); + _stp_relay_data.dropped_file = NULL; +- _stp_relay_data.rchan = NULL; + + /* Create "dropped" file. */ + _stp_relay_data.dropped_file +@@ -306,6 +316,7 @@ static int _stp_transport_data_fs_init(void) + + _stp_relay_data.dropped_file->d_inode->i_uid = KUIDT_INIT(_stp_uid); + _stp_relay_data.dropped_file->d_inode->i_gid = KGIDT_INIT(_stp_gid); ++#endif + + /* Create "trace" file. */ + npages = _stp_subbuf_size * _stp_nsubbufs; +-- +1.8.3.1 + diff --git a/SOURCES/rhbz1035752.patch b/SOURCES/rhbz1035752.patch new file mode 100644 index 0000000..4d06bad --- /dev/null +++ b/SOURCES/rhbz1035752.patch @@ -0,0 +1,108 @@ +From 735972b4c681efeff3c4137816cb913174a839be Mon Sep 17 00:00:00 2001 +From: Jonathan Lebon +Date: Mon, 2 Dec 2013 11:17:05 -0500 +Subject: [PATCH 1/2] Resolves: #1035752 + +Upstream commit e7d52b3. +--- + csclient.cxx | 2 +- + stap-serverd.cxx | 34 ++++++++++++++++++---------------- + 2 files changed, 19 insertions(+), 17 deletions(-) + +diff --git a/csclient.cxx b/csclient.cxx +index cce5428..4cfeb08 100644 +--- a/csclient.cxx ++++ b/csclient.cxx +@@ -829,7 +829,7 @@ compile_server_client::passes_0_4 () + << TIMESPRINT + << endl; + } +- if (rc) ++ if (rc && !s.listing_mode) + { + clog << _("Passes: via server failed. Try again with another '-v' option.") << endl; + } +diff --git a/stap-serverd.cxx b/stap-serverd.cxx +index 53a8d3a..035d06c 100644 +--- a/stap-serverd.cxx ++++ b/stap-serverd.cxx +@@ -63,7 +63,7 @@ extern "C" { + using namespace std; + + static void cleanup (); +-static PRStatus spawn_and_wait (const vector &argv, ++static PRStatus spawn_and_wait (const vector &argv, int *result, + const char* fd0, const char* fd1, const char* fd2, + const char *pwd, const vector& envVec = vector ()); + +@@ -1234,18 +1234,19 @@ handleRequest (const string &requestDirName, const string &responseDirName, stri + get_stap_locale (staplang, envVec, stapstderr, &client_version); + + /* All ready, let's run the translator! */ +- rc = spawn_and_wait(stapargv, "/dev/null", stapstdout.c_str (), stapstderr.c_str (), +- requestDirName.c_str (), envVec); ++ int staprc; ++ rc = spawn_and_wait(stapargv, &staprc, "/dev/null", stapstdout.c_str (), ++ stapstderr.c_str (), requestDirName.c_str (), envVec); ++ if (rc != PR_SUCCESS) ++ { ++ server_error(_("Failed spawning translator")); ++ return; ++ } + + /* Save the RC */ +- string staprc = responseDirName + "/rc"; +- f = fopen(staprc.c_str (), "w"); +- if (f) +- { +- /* best effort basis */ +- fprintf(f, "%d", rc); +- fclose(f); +- } ++ ofstream ofs((responseDirName + "/rc").c_str()); ++ ofs << staprc; ++ ofs.close(); + + // In unprivileged modes, if we have a module built, we need to sign the sucker. + privilege_t privilege = getRequestedPrivilege (stapargv); +@@ -1316,7 +1317,7 @@ handleRequest (const string &requestDirName, const string &responseDirName, stri + /* A front end for stap_spawn that handles stdin, stdout, stderr, switches to a working + directory and returns overall success or failure. */ + static PRStatus +-spawn_and_wait (const vector &argv, ++spawn_and_wait (const vector &argv, int *spawnrc, + const char* fd0, const char* fd1, const char* fd2, + const char *pwd, const vector& envVec) + { +@@ -1380,8 +1381,8 @@ spawn_and_wait (const vector &argv, + return PR_FAILURE; + } + +- rc = stap_waitpid (0, pid); +- if (rc == -1) ++ *spawnrc = stap_waitpid (0, pid); ++ if (*spawnrc == -1) + { + server_error (_("Error in waitpid")); + return PR_FAILURE; +@@ -1540,14 +1541,15 @@ handle_connection (void *arg) + handleRequest(requestDirName, responseDirName, stapstderr); + + /* Zip the response. */ ++ int ziprc; + argv.clear (); + argv.push_back ("zip"); + argv.push_back ("-q"); + argv.push_back ("-r"); + argv.push_back (responseFileName); + argv.push_back ("."); +- rc = spawn_and_wait (argv, NULL, NULL, NULL, responseDirName); +- if (rc != PR_SUCCESS) ++ rc = spawn_and_wait (argv, &ziprc, NULL, NULL, NULL, responseDirName); ++ if (rc != PR_SUCCESS || ziprc != 0) + { + server_error (_("Unable to compress server response")); + goto cleanup; +-- +1.8.3.1 + diff --git a/SOURCES/rhbz1035850.patch b/SOURCES/rhbz1035850.patch new file mode 100644 index 0000000..a56047a --- /dev/null +++ b/SOURCES/rhbz1035850.patch @@ -0,0 +1,122 @@ +From 10632b637aa12614e36ef83c7762bd44bef80716 Mon Sep 17 00:00:00 2001 +From: David Smith +Date: Tue, 3 Dec 2013 10:52:37 -0600 +Subject: [PATCH 2/2] Resolves: #1035850 + +Upstream commit f112949. +--- + testsuite/systemtap.examples/process/pfiles.stp | 54 +++++++++++++++++++++++++ + 1 file changed, 54 insertions(+) + +diff --git a/testsuite/systemtap.examples/process/pfiles.stp b/testsuite/systemtap.examples/process/pfiles.stp +index 6f5a834..b2bdbd8 100755 +--- a/testsuite/systemtap.examples/process/pfiles.stp ++++ b/testsuite/systemtap.examples/process/pfiles.stp +@@ -77,6 +77,10 @@ + #include + #include + #include ++#ifdef CONFIG_USER_NS ++#include ++#include ++#endif + %} + + function task_valid_file_handle:long (task:long, fd:long) %{ /* pure */ +@@ -199,6 +203,9 @@ function task_file_handle_uid:long (task:long, fd:long) %{ /* pure */ + struct task_struct *p = (struct task_struct *)((long)STAP_ARG_task); + struct files_struct *files; + struct file *filp; ++#ifdef CONFIG_USER_NS ++ struct user_namespace *ns = NULL; ++#endif + + rcu_read_lock(); + if ((files = kread(&p->files)) && +@@ -207,7 +214,25 @@ function task_file_handle_uid:long (task:long, fd:long) %{ /* pure */ + /* git commit d76b0d9b */ + const struct cred *cred; + if ((cred = kread(&filp->f_cred))) { ++#ifdef CONFIG_USER_NS ++ ns = get_user_ns(task_cred_xxx(p, user_ns)); ++ if (ns) { ++ // We call kderef_buffer() here to ++ // ensure the memory at the kuid_t ++ // location is valid to read. We can't ++ // use kderef()/kread(), since they ++ // only handle data with a size of 1, ++ // 2, 4, or 8 bytes. ++ kderef_buffer(NULL, &cred->fsuid, ++ sizeof(kuid_t)); ++ STAP_RETVALUE = from_kuid(ns, cred->fsuid); ++ } ++ else ++ STAP_RETVALUE = -1; ++ ++#else /* ! CONFIG_USER_NS */ + STAP_RETVALUE = kread(&cred->fsuid); ++#endif /* ! CONFIG_USER_NS */ + } + #else + STAP_RETVALUE = kread(&filp->f_uid); +@@ -215,6 +240,10 @@ function task_file_handle_uid:long (task:long, fd:long) %{ /* pure */ + } + + CATCH_DEREF_FAULT(); ++#ifdef CONFIG_USER_NS ++ if (ns) ++ put_user_ns(ns); ++#endif + rcu_read_unlock(); + %} + +@@ -222,6 +251,9 @@ function task_file_handle_gid:long (task:long, fd:long) %{ /* pure */ + struct task_struct *p = (struct task_struct *)((long)STAP_ARG_task); + struct files_struct *files; + struct file *filp; ++#ifdef CONFIG_USER_NS ++ struct user_namespace *ns = NULL; ++#endif + + rcu_read_lock(); + if ((files = kread(&p->files)) && +@@ -230,7 +262,25 @@ function task_file_handle_gid:long (task:long, fd:long) %{ /* pure */ + /* git commit d76b0d9b */ + const struct cred *cred; + if ((cred = kread(&filp->f_cred))) { ++#ifdef CONFIG_USER_NS ++ ns = get_user_ns(task_cred_xxx(p, user_ns)); ++ if (ns) { ++ // We call kderef_buffer() here to ++ // ensure the memory at the kgid_t ++ // location is valid to read. We can't ++ // use kderef()/kread(), since they ++ // only handle data with a size of 1, ++ // 2, 4, or 8 bytes. ++ kderef_buffer(NULL, &cred->fsgid, ++ sizeof(kgid_t)); ++ STAP_RETVALUE = from_kgid(ns, cred->fsgid); ++ } ++ else ++ STAP_RETVALUE = -1; ++ ++#else /* ! CONFIG_USER_NS */ + STAP_RETVALUE = kread(&cred->fsgid); ++#endif /* ! CONFIG_USER_NS */ + } + #else + STAP_RETVALUE = kread(&filp->f_gid); +@@ -238,6 +288,10 @@ function task_file_handle_gid:long (task:long, fd:long) %{ /* pure */ + } + + CATCH_DEREF_FAULT(); ++#ifdef CONFIG_USER_NS ++ if (ns) ++ put_user_ns(ns); ++#endif + rcu_read_unlock(); + %} + +-- +1.8.3.1 + diff --git a/SOURCES/rhbz1044429.patch b/SOURCES/rhbz1044429.patch new file mode 100644 index 0000000..910b98d --- /dev/null +++ b/SOURCES/rhbz1044429.patch @@ -0,0 +1,1278 @@ +From 94b9fcc03560b36932405727759a5621966cd212 Mon Sep 17 00:00:00 2001 +From: Jonathan Lebon +Date: Fri, 13 Dec 2013 16:37:57 -0500 +Subject: BZ1044429: fix client.exp and improve client/server + +--- + csclient.cxx | 342 ++++++++++++---------- + csclient.h | 4 +- + nsscommon.cxx | 11 +- + testsuite/lib/systemtap.exp | 1 + + testsuite/systemtap.server/client.exp | 333 ++++++++++----------- + testsuite/systemtap.server/server_args.exp | 17 +- + testsuite/systemtap.server/server_concurrency.exp | 4 +- + 7 files changed, 373 insertions(+), 339 deletions(-) + +diff --git a/csclient.cxx b/csclient.cxx +index cce5428..568cc8f 100644 +--- a/csclient.cxx ++++ b/csclient.cxx +@@ -1,6 +1,6 @@ + /* + Compile server client functions +- Copyright (C) 2010-2013 Red Hat Inc. ++ Copyright (C) 2010-2014 Red Hat Inc. + + This file is part of systemtap, and is free software. You can + redistribute it and/or modify it under the terms of the GNU General +@@ -88,66 +88,71 @@ nsscommon_error (const char *msg, int logit __attribute ((unused))) + // Information about compile servers. + struct compile_server_info + { +- compile_server_info () ++ compile_server_info () : port(0), fully_specified(false) + { + memset (& address, 0, sizeof (address)); + } + + string host_name; + PRNetAddr address; ++ unsigned short port; ++ bool fully_specified; + string version; + string sysinfo; + string certinfo; + + bool empty () const + { +- return this->host_name.empty () && ! this->hasAddress (); ++ return this->host_name.empty () && ! this->hasAddress () && certinfo.empty (); + } + bool hasAddress () const + { + return this->address.raw.family != 0; + } +- unsigned short port () const +- { +- if (this->address.raw.family == PR_AF_INET) +- return ntohs (this->address.inet.port); +- if (this->address.raw.family == PR_AF_INET6) +- return ntohs (this->address.ipv6.port); +- return 0; +- } +- unsigned short setPort (unsigned short port) ++ unsigned short setAddressPort (unsigned short port) + { + if (this->address.raw.family == PR_AF_INET) + return this->address.inet.port = htons (port); + if (this->address.raw.family == PR_AF_INET6) + return this->address.ipv6.port = htons (port); ++ assert (0); + return 0; + } ++ bool isComplete () const ++ { ++ return this->hasAddress () && port != 0; ++ } + + bool operator== (const compile_server_info &that) const + { +- // If both ip addressed are not set, then the host names must match, otherwise +- // the addresses must match. +- if (! this->hasAddress() || ! that.hasAddress()) ++ // If one item or the other has only a name, and possibly a port specified, ++ // then allow a match by name and port only. This is so that the user can specify ++ // names which are returned by avahi, but are not dns resolvable. ++ // Otherwise, we will ignore the host_name. ++ if ((! this->hasAddress() && this->version.empty () && ++ this->sysinfo.empty () && this->certinfo.empty ()) || ++ (! that.hasAddress() && that.version.empty () && ++ that.sysinfo.empty () && that.certinfo.empty ())) + { + if (this->host_name != that.host_name) + return false; + } +- else if (this->address != that.address) +- return false; + + // Compare the other fields only if they have both been set. +- if (this->port() != 0 && that.port() != 0 && +- this->port() != that.port()) ++ if (this->hasAddress() && that.hasAddress() && ++ this->address != that.address) ++ return false; ++ if (this->port != 0 && that.port != 0 && ++ this->port != that.port) + return false; + if (! this->version.empty () && ! that.version.empty () && +- this->version != that.version) ++ this->version != that.version) + return false; + if (! this->sysinfo.empty () && ! that.sysinfo.empty () && +- this->sysinfo != that.sysinfo) ++ this->sysinfo != that.sysinfo) + return false; + if (! this->certinfo.empty () && ! that.certinfo.empty () && +- this->certinfo != that.certinfo) ++ this->certinfo != that.certinfo) + return false; + + return true; // They are equal +@@ -179,6 +184,14 @@ preferred_order (vector &servers) + sort (servers.begin (), servers.end ()); + } + ++struct resolved_host ++{ ++ string host_name; ++ PRNetAddr address; ++ resolved_host(string chost_name, PRNetAddr caddress): ++ host_name(chost_name), address(caddress) {} ++}; ++ + struct compile_server_cache + { + vector default_servers; +@@ -187,7 +200,7 @@ struct compile_server_cache + vector signing_servers; + vector online_servers; + vector all_servers; +- map > resolved_servers; ++ map > resolved_hosts; + }; + + // For filtering queries. +@@ -234,7 +247,7 @@ static void resolve_host (systemtap_session& s, compile_server_info &server, vec + // ----------------------------------------------------- + // NSS related code used by the compile server client + // ----------------------------------------------------- +-static void add_server_trust (systemtap_session &s, const string &cert_db_path, const vector &server_list); ++static void add_server_trust (systemtap_session &s, const string &cert_db_path, vector &server_list); + static void revoke_server_trust (systemtap_session &s, const string &cert_db_path, const vector &server_list); + static void get_server_info_from_db (systemtap_session &s, vector &servers, const string &cert_db_path); + +@@ -1132,10 +1145,10 @@ compile_server_client::find_and_connect_to_server () + i != specified_servers.end (); + ++i) + { +- // If we have an ip address and port number, then just use the one we've +- // been given. Otherwise, check for matching online servers and try their ++ // If we have an ip address and were given a port number, then just use the one we've ++ // been given. Otherwise, check for matching compatible online servers and try their + // ip addresses and ports. +- if (i->hasAddress() && i->port() != 0) ++ if (i->hasAddress() && i->fully_specified) + add_server_info (*i, server_list); + else + { +@@ -1145,8 +1158,8 @@ compile_server_client::find_and_connect_to_server () + + // If no specific server (port) has been specified, + // then we'll need the servers to be +- // compatible and possible trusted as signers as well. +- if (i->port() == 0) ++ // compatible and possibly trusted as signers as well. ++ if (! i->fully_specified) + { + get_or_keep_compatible_server_info (s, online_servers, true/*keep*/); + if (! pr_contains (s.privilege, pr_stapdev)) +@@ -1227,7 +1240,7 @@ compile_server_client::find_and_connect_to_server () + + int + compile_server_client::compile_using_server ( +- const vector &servers ++ vector &servers + ) + { + // Make sure NSPR is initialized. Must be done before NSS is initialized +@@ -1275,14 +1288,16 @@ compile_server_client::compile_using_server ( + server_zipfile = s.tmpdir + "/server.zip"; + + // Try each server in turn. +- for (vector::const_iterator j = servers.begin (); ++ for (vector::iterator j = servers.begin (); + j != servers.end (); + ++j) + { + // At a minimum we need an ip_address along with a port + // number in order to contact the server. +- if (! j->hasAddress() || j->port() == 0) ++ if (! j->hasAddress() || j->port == 0) + continue; ++ // Set the port within the address. ++ j->setAddressPort (j->port); + + if (s.verbose >= 2) + clog << _F("Attempting SSL connection with %s\n" +@@ -1673,7 +1688,7 @@ static void + add_server_trust ( + systemtap_session &s, + const string &cert_db_path, +- const vector &server_list ++ vector &server_list + ) + { + // Get a list of servers already trusted. This opens the database, so do it +@@ -1716,7 +1731,7 @@ add_server_trust ( + // Iterate over the servers to become trusted. Contact each one and + // add it to the list of trusted servers if it is not already trusted. + // client_connect will issue any error messages. +- for (vector::const_iterator server = server_list.begin(); ++ for (vector::iterator server = server_list.begin(); + server != server_list.end (); + ++server) + { +@@ -1735,10 +1750,14 @@ add_server_trust ( + trust_already_in_place (*server, server_list, cert_db_path, false/*revoking*/); + continue; + } ++ + // At a minimum we need an ip_address along with a port + // number in order to contact the server. +- if (! server->hasAddress() || server->port() == 0) ++ if (! server->hasAddress() || server->port == 0) + continue; ++ // Set the port within the address. ++ server->setAddressPort (server->port); ++ + int rc = client_connect (*server, NULL, NULL, "permanent"); + if (rc != SUCCESS) + { +@@ -2076,8 +2095,8 @@ ostream &operator<< (ostream &s, const compile_server_info &i) + else + s << "offline"; + s << " port="; +- if (i.port() != 0) +- s << i.port(); ++ if (i.port != 0) ++ s << i.port; + else + s << "unknown"; + s << " sysinfo=\""; +@@ -2586,7 +2605,8 @@ isPort (const char *pstr, compile_server_info &server_info) + clog << _F("Invalid port number specified: %s", pstr) << endl; + return false; + } +- server_info.setPort (p); ++ server_info.port = p; ++ server_info.fully_specified = true; + return true; + } + +@@ -2665,8 +2685,10 @@ isIPv6 (const string &server, compile_server_info &server_info) + if (! empty && components.size() != 8) + return false; // Not a valid IPv6 address + +- // Calls to setPort and isPort need to know that this is an IPv6 address. +- server_info.address.raw.family = PR_AF_INET6; ++ // Try to convert the string to an address. ++ PRStatus prStatus = PR_StringToNetAddr (ip.c_str(), & server_info.address); ++ if (prStatus != PR_SUCCESS) ++ return false; + + // Examine the optional port + if (portIx != string::npos) +@@ -2683,10 +2705,8 @@ isIPv6 (const string &server, compile_server_info &server_info) + } + } + else +- server_info.setPort (0); ++ server_info.port = 0; + +- // Treat the ip address string like a host name. +- server_info.host_name = ip; + return true; // valid IPv6 address. + } + +@@ -2703,20 +2723,20 @@ isIPv4 (const string &server, compile_server_info &server_info) + if (components.size() > 2) + return false; // Not a valid IPv4 address + +- // Separate the host from the port (if any). +- string host; ++ // Separate the address from the port (if any). ++ string addr; + string port; + if (components.size() <= 1) +- host = server; ++ addr = server; + else { +- host = components[0]; ++ addr = components[0]; + port = components[1]; + } + +- // Separate the host components. ++ // Separate the address components. + // There must be exactly 4 components. + components.clear (); +- tokenize (server, components, "."); ++ tokenize (addr, components, "."); + if (components.size() != 4) + return false; // Not a valid IPv4 address + +@@ -2732,8 +2752,10 @@ isIPv4 (const string &server, compile_server_info &server_info) + return false; // Not a valid IPv4 address + } + +- // Calls to setPort and isPort need to know that this is an IPv4 address. +- server_info.address.raw.family = PR_AF_INET; ++ // Try to convert the string to an address. ++ PRStatus prStatus = PR_StringToNetAddr (addr.c_str(), & server_info.address); ++ if (prStatus != PR_SUCCESS) ++ return false; + + // Examine the optional port + if (! port.empty ()) { +@@ -2741,10 +2763,8 @@ isIPv4 (const string &server, compile_server_info &server_info) + return false; // not a valid port + } + else +- server_info.setPort (0); ++ server_info.port = 0; + +- // Treat the ip address string like a host name. +- server_info.host_name = host; + return true; // valid IPv4 address. + } + +@@ -2754,8 +2774,6 @@ isCertSerialNumber (const string &server, compile_server_info &server_info) + // This function assumes that we have already ruled out the server spec being an IPv6 address. + // Certificate serial numbers are 5 fields separated by colons plus an optional 6th decimal + // field specifying a port. +- // Assume IPv4 (for now) when storing the port. +- server_info.address.raw.family = PR_AF_INET; + assert (! server.empty()); + string host = server; + vector components; +@@ -2782,8 +2800,6 @@ isDomain (const string &server, compile_server_info &server_info) + { + // Accept one or two components separated by a colon. The first will be the domain name and + // the second must a port number. +- // Assume IPv4 (for now) when storing the port. +- server_info.address.raw.family = PR_AF_INET; + assert (! server.empty()); + string host = server; + vector components; +@@ -2858,50 +2874,69 @@ get_specified_server_info ( + // Check for IPv6 addresses first. It reduces the amount of checking necessary for + // certificate serial numbers. + compile_server_info server_info; +- vector known_servers; ++ vector resolved_servers; + if (isIPv6 (server, server_info) || isIPv4 (server, server_info) || +- isDomain (server, server_info)) ++ isCertSerialNumber (server, server_info)) + { +- // Resolve this host and add any information that is discovered. +- // Try to augment the resolved servers with information about known servers. +- // There may be no intersection. +- get_all_server_info (s, known_servers); +- +- vector resolved_servers; ++ // An address or cert serial number has been specified. ++ // No resolution is needed. ++ resolved_servers.push_back (server_info); ++ } ++ else if (isDomain (server, server_info)) ++ { ++ // Try to resolve the given name. + resolve_host (s, server_info, resolved_servers); +- +- vector common_servers = resolved_servers; +- keep_common_server_info (known_servers, common_servers); +- if (! common_servers.empty ()) +- add_server_info (common_servers, resolved_servers); +- +- if (s.verbose >= 3) +- { +- clog << _F("Servers matching %s: ", server.c_str()) << endl; +- clog << resolved_servers; +- } +- add_server_info (resolved_servers, specified_servers); +- } +- else if (isCertSerialNumber (server, server_info)) +- { +- // The host could not be resolved. Try resolving it as a certificate serial +- // number. Look for all known servers with this serial number and (optional) +- // port number. +- get_all_server_info (s, known_servers); +- keep_server_info_with_cert_and_port (s, server_info, known_servers); +- if (s.verbose >= 3) +- { +- clog << _F("Servers matching %s: ", server.c_str()) << endl; +- clog << known_servers; +- } +- +- add_server_info (known_servers, specified_servers); + } + else + { + clog << _F("Invalid server specification for --use-server: %s", server.c_str()) + << endl; ++ continue; + } ++ ++ // Now examine the server(s) identified and add them to the list of specified ++ // servers. ++ vector known_servers; ++ vector new_servers; ++ for (vector::iterator i = resolved_servers.begin(); ++ i != resolved_servers.end(); ++ ++i) ++ { ++ // If this item was fully specified, then just add it. ++ if (i->fully_specified) ++ add_server_info (*i, new_servers); ++ else { ++ // It was not fully specified, so we need additional info. Try ++ // to get it by matching what we have against other known servers. ++ if (known_servers.empty ()) ++ get_all_server_info (s, known_servers); ++ ++ // See if this server spec matches that of a known server ++ vector matched_servers = known_servers; ++ keep_common_server_info (*i, matched_servers); ++ ++ // If this server spec matches one or more known servers, then add the ++ // augmented info to the specified_servers. Otherwise, if this server ++ // spec is complete, then add it directly. Otherwise this server spec ++ // is incomplete. ++ if (! matched_servers.empty()) ++ add_server_info (matched_servers, new_servers); ++ else if (i->isComplete ()) ++ add_server_info (*i, new_servers); ++ else if (s.verbose >= 3) ++ clog << _("Incomplete server spec: ") << *i << endl; ++ } ++ } ++ ++ if (s.verbose >= 3) ++ { ++ clog << _F("Servers matching %s: ", server.c_str()) << endl; ++ clog << new_servers; ++ } ++ ++ // Add the newly identified servers to the list. ++ if (! new_servers.empty()) ++ add_server_info (new_servers, specified_servers); + } // Loop over --use-server options + } // -- use-server specified + +@@ -3087,13 +3122,16 @@ keep_server_info_with_cert_and_port ( + continue; + } + if (servers[i].certinfo == server.certinfo && +- (servers[i].port() == 0 || server.port() == 0 || +- servers[i].port() == server.port())) ++ (servers[i].port == 0 || server.port == 0 || ++ servers[i].port == server.port)) + { + // If the server is not online, then use the specified + // port, if any. +- if (servers[i].port() == 0) +- servers[i].setPort (server.port()); ++ if (servers[i].port == 0) ++ { ++ servers[i].port = server.port; ++ servers[i].fully_specified = server.fully_specified; ++ } + ++i; + continue; + } +@@ -3110,8 +3148,8 @@ resolve_host ( + vector &resolved_servers + ) + { +- vector& cached_servers = cscache(s)->resolved_servers[server.host_name]; +- if (cached_servers.empty ()) ++ vector& cached_hosts = cscache(s)->resolved_hosts[server.host_name]; ++ if (cached_hosts.empty ()) + { + // The server's host_name member is a string containing either a host name or an ip address. + // Either is acceptable for lookup. +@@ -3128,10 +3166,8 @@ resolve_host ( + // Failure to resolve will result in an appropriate message later, if other methods fail. + if (rc != 0) + { +- // At a minimum, return the information we were given. + if (s.verbose >= 6) + clog << _F("%s not found: %s", lookup_name, gai_strerror (rc)) << endl; +- add_server_info (server, cached_servers); + } + else + { +@@ -3139,28 +3175,23 @@ resolve_host ( + assert (addr_info); + for (const struct addrinfo *ai = addr_info; ai != NULL; ai = ai->ai_next) + { +- // Start with the info we were given. +- compile_server_info new_server = server; ++ PRNetAddr new_address; + + // We support IPv4 and IPv6, Ignore other protocols, + if (ai->ai_family == AF_INET) + { + // IPv4 Address + struct sockaddr_in *ip = (struct sockaddr_in *)ai->ai_addr; +- new_server.address.inet.family = PR_AF_INET; +- if (ip->sin_port != 0) +- new_server.address.inet.port = ip->sin_port; +- new_server.address.inet.ip = ip->sin_addr.s_addr; ++ new_address.inet.family = PR_AF_INET; ++ new_address.inet.ip = ip->sin_addr.s_addr; + } + else if (ai->ai_family == AF_INET6) + { + // IPv6 Address + struct sockaddr_in6 *ip = (struct sockaddr_in6 *)ai->ai_addr; +- new_server.address.ipv6.family = PR_AF_INET6; +- if (ip->sin6_port != 0) +- new_server.address.ipv6.port = ip->sin6_port; +- new_server.address.ipv6.scope_id = ip->sin6_scope_id; +- copyAddress (new_server.address.ipv6.ip, ip->sin6_addr); ++ new_address.ipv6.family = PR_AF_INET6; ++ new_address.ipv6.scope_id = ip->sin6_scope_id; ++ copyAddress (new_address.ipv6.ip, ip->sin6_addr); + } + else + continue; +@@ -3169,25 +3200,54 @@ resolve_host ( + char hbuf[NI_MAXHOST]; + int status = getnameinfo (ai->ai_addr, ai->ai_addrlen, hbuf, sizeof (hbuf), NULL, 0, + NI_NAMEREQD | NI_IDN); +- if (status == 0) +- new_server.host_name = hbuf; ++ if (status != 0) ++ hbuf[0] = '\0'; + +- // Add the new resolved server to the list. +- add_server_info (new_server, cached_servers); ++ resolved_host *new_host = new resolved_host(hbuf, new_address); ++ cached_hosts.push_back(*new_host); + } + } + if (addr_info) + freeaddrinfo (addr_info); // free the linked list +- +- if (s.verbose >= 6) +- { +- clog << _F("%s resolves to:", lookup_name) << endl; +- clog << cached_servers; +- } + } + +- // Add the information, but not duplicates. +- add_server_info (cached_servers, resolved_servers); ++ // If no addresses were resolved, then return the info we were given. ++ if (cached_hosts.empty()) ++ add_server_info (server, resolved_servers); ++ else { ++ // We will add a new server for each address resolved ++ vector new_servers; ++ for (vector::const_iterator it = cached_hosts.begin(); ++ it != cached_hosts.end(); ++it) ++ { ++ // Start with the info we were given ++ compile_server_info new_server = server; ++ ++ // NB: do not overwrite port info ++ if (it->address.raw.family == AF_INET) ++ { ++ new_server.address.inet.family = PR_AF_INET; ++ new_server.address.inet.ip = it->address.inet.ip; ++ } ++ else // AF_INET6 ++ { ++ new_server.address.ipv6.family = PR_AF_INET6; ++ new_server.address.ipv6.scope_id = it->address.ipv6.scope_id; ++ new_server.address.ipv6.ip = it->address.ipv6.ip; ++ } ++ if (!it->host_name.empty()) ++ new_server.host_name = it->host_name; ++ add_server_info (new_server, new_servers); ++ } ++ ++ if (s.verbose >= 6) ++ { ++ clog << _F("%s resolves to:", server.host_name.c_str()) << endl; ++ clog << new_servers; ++ } ++ ++ add_server_info (new_servers, resolved_servers); ++ } + } + + #if HAVE_AVAHI +@@ -3268,12 +3328,12 @@ void resolve_callback( + // We support both IPv4 and IPv6. Ignore other protocols. + if (protocol == AVAHI_PROTO_INET6) { + info.address.ipv6.family = PR_AF_INET6; +- info.address.ipv6.port = htons (port); + info.address.ipv6.scope_id = interface; ++ info.port = port; + } + else if (protocol == AVAHI_PROTO_INET) { + info.address.inet.family = PR_AF_INET; +- info.address.inet.port = htons (port); ++ info.port = port; + } + else + break; +@@ -3388,7 +3448,6 @@ get_or_keep_online_server_info ( + online_servers.push_back (compile_server_info ()); + #if HAVE_AVAHI + // Must predeclare these due to jumping on error to fail: +- unsigned limit; + vector avahi_servers; + + // Initialize. +@@ -3449,25 +3508,6 @@ get_or_keep_online_server_info ( + clog << avahi_servers; + } + +- // Resolve each server discovered, in case there are alternate ways to reach them +- // (e.g. localhost). +- limit = avahi_servers.size (); +- for (unsigned i = 0; i < limit; ++i) +- { +- compile_server_info &avahi_server = avahi_servers[i]; +- +- // Delete the domain, if it is '.local' +- string &host_name = avahi_server.host_name; +- string::size_type dot_index = host_name.find ('.'); +- assert (dot_index != 0); +- string domain = host_name.substr (dot_index + 1); +- if (domain == "local") +- host_name = host_name.substr (0, dot_index); +- +- // Add it to the list of servers, unless it is duplicate. +- resolve_host (s, avahi_server, online_servers); +- } +- + // Merge with the list of servers, as obtained by avahi. + add_server_info (avahi_servers, online_servers); + +@@ -3619,15 +3659,19 @@ merge_server_info ( + compile_server_info &target + ) + { +- if (target.host_name.empty ()) ++ // Copy the host name if the source has one. ++ if (! source.host_name.empty()) + target.host_name = source.host_name; + // Copy the address unconditionally, if the source has an address, even if they are already + // equal. The source address may be an IPv6 address with a scope_id that the target is missing. + assert (! target.hasAddress () || ! source.hasAddress () || source.address == target.address); + if (source.hasAddress ()) + copyNetAddr (target.address, source.address); +- if (target.port() == 0) +- target.setPort (source.port()); ++ if (target.port == 0) ++ { ++ target.port = source.port; ++ target.fully_specified = source.fully_specified; ++ } + if (target.sysinfo.empty ()) + target.sysinfo = source.sysinfo; + if (target.version.empty ()) +diff --git a/csclient.h b/csclient.h +index b7eeda4..e4508ea 100644 +--- a/csclient.h ++++ b/csclient.h +@@ -1,5 +1,5 @@ + // -*- C++ -*- +-// Copyright (C) 2010-2011 Red Hat Inc. ++// Copyright (C) 2010-2014 Red Hat Inc. + // + // This file is part of systemtap, and is free software. You can + // redistribute it and/or modify it under the terms of the GNU General +@@ -35,7 +35,7 @@ private: + ); + int add_package_args (); + int add_package_arg (const std::string &arg); +- int compile_using_server (const std::vector &servers); ++ int compile_using_server (std::vector &servers); + int add_localization_variables(); + + int read_from_file (const std::string &fname, int &data); +diff --git a/nsscommon.cxx b/nsscommon.cxx +index 70aac54..78e38b0 100644 +--- a/nsscommon.cxx ++++ b/nsscommon.cxx +@@ -1,7 +1,7 @@ + /* + Common functions used by the NSS-aware code in systemtap. + +- Copyright (C) 2009-2013 Red Hat Inc. ++ Copyright (C) 2009-2014 Red Hat Inc. + + This file is part of systemtap, and is free software. You can + redistribute it and/or modify it under the terms of the GNU General Public +@@ -998,12 +998,19 @@ gen_cert_db (const string &db_path, const string &extraDnsNames, bool use_passwo + goto error; + } + +- // Now, generate the cert. We need our host name and the supplied additional dns names (if any). ++ // For the cert, we need our host name. + struct utsname utsname; + uname (& utsname); + dnsNames = utsname.nodename; ++ ++ // Because avahi identifies hosts using a ".local" domain, add one to the list of names. ++ dnsNames += string(",") + dnsNames + ".local"; ++ ++ // Add any extra names that were supplied. + if (! extraDnsNames.empty ()) + dnsNames += "," + extraDnsNames; ++ ++ // Now, generate the cert. + cert = create_cert (cr, dnsNames); + CERT_DestroyCertificateRequest (cr); + if (! cert) +diff --git a/testsuite/lib/systemtap.exp b/testsuite/lib/systemtap.exp +index d4e4d85..64bbed1 100644 +--- a/testsuite/lib/systemtap.exp ++++ b/testsuite/lib/systemtap.exp +@@ -244,6 +244,7 @@ proc setup_server { args } { + } + + # Make sure that stap can find the server. ++ exec sleep 1 + set use_server --use-server + set res [catch { exec stap --list-servers=online,trusted,compatible >& stap-list-servers.out } looksee] + verbose -log "stap --list-servers returned: res==$res" +diff --git a/testsuite/systemtap.server/client.exp b/testsuite/systemtap.server/client.exp +index f0d0728..41a06cc 100644 +--- a/testsuite/systemtap.server/client.exp ++++ b/testsuite/systemtap.server/client.exp +@@ -1,3 +1,6 @@ ++# In this test, we are using arrays as sets. The key itself does not matter, ++# only the value ++ + # many of these tests use as_root + if {! [installtest_p]} { return } + if {! [nss_p]} { return } +@@ -5,37 +8,111 @@ if {! [nss_p]} { return } + # Let's start with a clean slate in terms of trust. + exec rm -fr $env(SYSTEMTAP_DIR)/ssl + +-# Compare two arrays. If equal, return 1, otherwise 0. +-# (Borrowed from http://wiki.tcl.tk/1032.) +-proc array_compare {array1 array2} { +- upvar 1 $array1 foo $array2 bar ++# arr given as list (e.g. [array_has [array get myarr] elem]) ++proc array_has {arr elem} { + +- if {![array exists foo]} { +- return -code error "$array1 is not an array" +- } +- if {![array exists bar]} { +- return -code error "$array2 is not an array" +- } +- if {[array size foo] != [array size bar]} { +- return 0 +- } ++ array set foo $arr + if {[array size foo] == 0} { ++ return 0 ++ } ++ ++ foreach {key val} [array get foo] { ++ if {[string equal $val $elem]} { ++ return 1 ++ } ++ } ++ ++ return 0 ++} ++ ++# Check if array1 is a subset of array2. Returns 1 if yes, otherwise 0. ++# (Modified from http://wiki.tcl.tk/1032.) ++proc array_in {array1 array2} { ++ upvar 1 $array1 sub $array2 super ++ ++ if {![array exists sub]} { ++ return -code error "$array1 is not an array" ++ } ++ if {![array exists super]} { ++ return -code error "$array2 is not an array" ++ } ++ if {[array size sub] > [array size super]} { ++ return 0 ++ } ++ if {[array size sub] == 0} { + return 1 + } + +- set keys [lsort -unique [concat [array names foo] [array names bar]]] +- if {[llength $keys] != [array size foo]} { +- return 0 +- } +- +- foreach key $keys { +- if {$foo($key) ne $bar($key)} { ++ foreach key [array names sub] { ++ if {![array_has [array get super] $sub($key)]} { + return 0 + } + } + return 1 + } + ++# Check if array1 and array2 have all the same elements ++proc array_equal {array1 array2} { ++ upvar 1 $array1 foo $array2 bar ++ return [array_in foo bar] \ ++ && [array_in bar foo] ++} ++ ++# Returns the union of the three arrays ++proc array_union {array1 array2 array3} { ++ upvar 1 $array1 foo $array2 bar $array3 baz ++ array unset ::union ++ ++ if {![array exists foo]} { ++ return -code error "$array1 is not an array" ++ } ++ if {![array exists bar]} { ++ return -code error "$array2 is not an array" ++ } ++ if {![array exists baz]} { ++ return -code error "$array3 is not an array" ++ } ++ ++ set n 0 ++ foreach key [array names foo] { ++ set ::union($n) $foo($key) ++ incr n ++ } ++ foreach key [array names bar] { ++ if {![array_has [array get ::union] $bar($key)]} { ++ set ::union($n) $bar($key) ++ incr n ++ } ++ } ++ foreach key [array names baz] { ++ if {![array_has [array get ::union] $baz($key)]} { ++ set ::union($n) $baz($key) ++ incr n ++ } ++ } ++} ++ ++# Returns all the elements in array_new not in array_old ++proc array_diff {array_new array_old} { ++ upvar 1 $array_new anew $array_old aold ++ array unset ::diff ++ ++ if {![array exists anew]} { ++ return -code error "$array_new is not an array" ++ } ++ if {![array exists aold]} { ++ return -code error "$array_old is not an array" ++ } ++ ++ set n 0 ++ foreach key [array names anew] { ++ if {![array_has [array get aold] $anew($key)]} { ++ set ::diff($n) $anew($key) ++ incr n ++ } ++ } ++} ++ + # Test the --list-servers option and return an array of the servers found. + proc list_servers { TEST_NAME SERVER_SPEC args } { + set failed 0 +@@ -82,7 +159,6 @@ proc list_servers { TEST_NAME SERVER_SPEC args } { + # Sometimes, we'll see a server running from the last test, if it + # hasn't quite died yet. So, make sure we get the same result twice. + list_servers "List existing online servers" online +-array unset eos1 + array set existing_online_servers [array get servers] + set i 0 + while {1} { +@@ -94,9 +170,9 @@ while {1} { + fail "List existing online servers: never got stable" + return + } +- ++ + verbose -log "verify existing online servers - attempt $i: [array size existing_online_servers] [array size eos2]" +- if {[array_compare existing_online_servers eos2]} { ++ if {[array_equal existing_online_servers eos2]} { + # Arrays are equal, we're done + break + } +@@ -120,37 +196,23 @@ list_servers "List all existing servers" all + array unset all_existing_servers + array set all_existing_servers [array get servers] + +-set test "Verify existing online server list" +-if {[array_compare existing_online_servers all_existing_servers]} { +- pass "$test" +-} else { +- fail "$test" +-} ++# First we create a union ++array_union existing_online_servers \ ++ existing_trusted_servers \ ++ existing_signing_servers ++array set existing_unioned_servers [array get union] + +-set test "Verify existing trusted server list" +-if {[array_compare existing_trusted_servers all_existing_servers]} { +- pass "$test" +-} else { +- fail "$test" +-} +- +-set test "Verify existing signing server list" +-if {[array_compare existing_signing_servers all_existing_servers]} { +- pass "$test" +-} else { +- fail "$test" +-} +- +-set test "Verify all existing server list" +-if {[array_compare existing_online_servers all_existing_servers]} { ++# Now we can compare ++set test "Verify existing server list" ++if {[array_equal existing_unioned_servers all_existing_servers]} { + pass "$test" + } else { + fail "$test" + } + + list_servers "List existing online servers (before start)" online +-array unset existing_online_servers1 +-array set existing_online_servers1 [array get servers] ++array unset existing_online_servers ++array set existing_online_servers [array get servers] + + # Now start our own server and make sure we can work with it. + if {! [setup_server] || $avahi_ok_p != 1} { +@@ -159,31 +221,22 @@ if {! [setup_server] || $avahi_ok_p != 1} { + } + + # Our server should now appear online, separate from the previously discovered +-# online servers. Note that our server could generate serveral listings +-# because it could appear at more than one ip address, ++# online servers. Note that our server could generate serveral listings because ++# it could appear at more than one ip address, + list_servers "List current online servers" online + array unset current_online_servers + array set current_online_servers [array get servers] + ++# array_diff will give us all the servers in current not in existing ++array_diff current_online_servers existing_online_servers ++array unset new_online_servers ++array set new_online_servers [array get diff] ++ + set test "New online servers" +-set n 0 +-foreach idx1 [array names current_online_servers] { +- set found 0 +- foreach idx2 [array names existing_online_servers] { +- if {"$existing_online_servers($idx2)" == "$current_online_servers($idx1)"} { +- set found 1 +- break +- } +- } +- if {$found == 0} { +- set new_online_servers($n) "$current_online_servers($idx1)" +- incr n +- } +-} +-if {$n == 0} { +- fail "$test" +-} else { ++if {[array size new_online_servers] > 0} { + pass "$test" ++} else { ++ fail "$test" + } + + # Our server should now be trusted, separate from the previously discovered +@@ -192,48 +245,27 @@ list_servers "List current trusted servers" online,trusted + array unset current_trusted_servers + array set current_trusted_servers [array get servers] + ++# array_diff will give us all the servers in current not in existing ++array_diff current_trusted_servers existing_trusted_servers ++array unset new_trusted_servers ++array set new_trusted_servers [array get diff] ++ + set test "New trusted servers" +-set n 0 +-foreach idx1 [array names current_trusted_servers] { +- set found 0 +- foreach idx2 [array names existing_trusted_servers] { +- if {"$existing_trusted_servers($idx2)" == "$current_trusted_servers($idx1)"} { +- set found 1 +- break +- } +- } +- if {$found == 0} { +- set new_trusted_servers($n) "$current_trusted_servers($idx1)" +- incr n +- } +-} +-if {$n == 0} { +- fail "$test" +-} else { ++if {[array size new_trusted_servers] > 0} { + pass "$test" ++} else { ++ fail "$test" + } + + # The new servers should automatically be trusted, so the new_trusted_servers +-# array should be a subset of the new_online_servers +-# array, but not necessarilty vice-versa, since new servers may have come +-# online independently of our testing. ++# array should be a subset of the new_online_servers array, but not necessarily ++# vice-versa, since new servers may have come online independently of our ++# testing. + set test "Verify new trusted server list" +-set failed 0 +-foreach idx1 [array names new_trusted_servers] { +- set found 0 +- foreach idx2 [array names new_online_servers] { +- if {"$new_trusted_servers($idx1)" == "$new_online_servers($idx2)"} { +- set found 1 +- break +- } +- } +- if {$found == 0} { +- set failed 1 +- fail "$test $idx1" +- } +-} +-if {$failed == 0} { ++if {[array_in new_trusted_servers new_online_servers]} { + pass "$test" ++} else { ++ fail "$test" + } + + # The newly trusted servers represent the server we just started. +@@ -247,7 +279,7 @@ array unset current_signing_servers + array set current_signing_servers [array get servers] + + set test "No new signing servers" +-if {[array_compare current_signing_servers existing_signing_servers]} { ++if {[array_equal current_signing_servers existing_signing_servers]} { + pass "$test" + } else { + fail "$test" +@@ -287,7 +319,7 @@ array unset current_trusted_servers + array set current_trusted_servers [array get servers] + + set test "No longer trusted after revokation by host name" +-if {[array_compare current_trusted_servers existing_trusted_servers]} { ++if {[array_equal current_trusted_servers existing_trusted_servers]} { + pass "$test" + } else { + fail "$test" +@@ -320,54 +352,24 @@ list_servers "List current trusted servers after reinstatement by ip address" on + array unset current_trusted_servers + array set current_trusted_servers [array get servers] + ++array_diff current_trusted_servers existing_trusted_servers ++array unset new_trusted_servers ++array set new_trusted_servers [array get diff] ++ + set test "New trusted servers after reinstatement by ip address" +-array unset new_trusted_servers +-set n 0 +-foreach idx1 [array names current_trusted_servers] { +- set found 0 +- foreach idx2 [array names existing_trusted_servers] { +- if {"$existing_trusted_servers($idx2)" == "$current_trusted_servers($idx1)"} { +- set found 1 +- break +- } +- } +- if {$found == 0} { +- set new_trusted_servers($n) "$current_trusted_servers($idx1)" +- incr n +- } +-} +-if {$n == 0} { +- fail "$test" +-} else { ++if {[array size new_trusted_servers] > 0} { + pass "$test" ++} else { ++ fail "$test" + } + + # The new_trusted_servers array should now match the our_servers array, since + # the our_servers array is a copy of the original new_trusted_servers array. +-set test "Number of new trusted servers matches after reinstatement by ip address" +-if {[array size new_trusted_servers] == [array size our_servers]} { +- pass "$test" +-} else { +- fail "$test" +-} + set test "New trusted servers matches after reinstatement by ip address" +-set n 0 +-foreach idx1 [array names new_trusted_servers] { +- set found 0 +- foreach idx2 [array names our_servers] { +- if {"$our_servers($idx2)" == "$new_trusted_servers($idx1)"} { +- set found 1 +- break +- } +- } +- if {$found == 1} { +- incr n +- } +-} +-if {$n != [array size new_trusted_servers]} { +- fail "$test" +-} else { ++if {[array_equal new_trusted_servers our_servers]} { + pass "$test" ++} else { ++ fail "$test" + } + + # Trust our server as a module signer. This must be done as root. Specify +@@ -394,28 +396,18 @@ list_servers "List current online signing servers" online,signer + array unset current_signing_servers + array set current_signing_servers [array get servers] + ++array_diff current_signing_servers existing_signing_servers ++array unset new_signing_servers ++array set new_signing_servers [array get diff] ++ + set test "New signing servers" +-set n 0 +-foreach idx1 [array names current_signing_servers] { +- set found 0 +- foreach idx2 [array names existing_signing_servers] { +- if {"$existing_signing_servers($idx2)" == "$current_signing_servers($idx1)"} { +- set found 1 +- break +- } +- } +- if {$found == 0} { +- set new_signing_servers($n) "$current_signing_servers($idx1)" +- incr n +- } +-} + if {$effective_pid == 0} { + setup_xfail *-*-* + } +-if {$n == 0} { +- fail "$test" +-} else { ++if {[array size new_signing_servers] > 0} { + pass "$test" ++} else { ++ fail "$test" + } + + # The new_signing_servers array should now match the our_servers array, since +@@ -428,26 +420,13 @@ if {$effective_pid == 0} { + if {[array size new_signing_servers] == [array size our_servers]} { + pass "$test" + set test "New signing servers matches" +- set n 0 +- foreach idx1 [array names new_signing_servers] { +- set found 0 +- foreach idx2 [array names our_servers] { +- if {"$our_servers($idx2)" == "$new_signing_servers($idx1)"} { +- set found 1 +- break +- } +- } +- if {$found == 1} { +- incr n +- } +- } + if {$effective_pid == 0} { + setup_xfail *-*-* + } +- if {$n != [array size new_signing_servers]} { +- fail "$test" +- } else { ++ if {[array_equal new_signing_servers our_servers]} { + pass "$test" ++ } else { ++ fail "$test" + } + } else { + fail "$test" +@@ -594,7 +573,7 @@ array unset current_signing_servers + array set current_signing_servers [array get servers] + + set test "No longer trusted as a signer after revokation" +-if {[array_compare current_signing_servers existing_signing_servers]} { ++if {[array_in current_signing_servers existing_signing_servers]} { + pass "$test" + } else { + fail "$test" +diff --git a/testsuite/systemtap.server/server_args.exp b/testsuite/systemtap.server/server_args.exp +index 2f5deed..91536a5 100644 +--- a/testsuite/systemtap.server/server_args.exp ++++ b/testsuite/systemtap.server/server_args.exp +@@ -66,20 +66,23 @@ proc stap_direct_and_with_client {stap options} { + verbose -log $res_stap_client + + # Now check the output +- set skip 0 ++ set skip_hostname_mode 0 + set n 0 + set expected [split $res_stap "\n"] + set received [split $res_stap_client "\n"] + foreach line $received { +- # Instructed to skip a line? +- if {$skip} { +- set skip [expr $skip - 1] +- verbose -log "skipping: $line" +- continue ++ # Instructed to skip hostnames? ++ if {$skip_hostname_mode} { ++ if {[regexp {^ \S+$} $line]} { ++ verbose -log "skipping: $line" ++ continue ++ } else { ++ set skip_hostname_mode 0 ++ } + } + # Ignore warnings about the domain name on the certificate not matching + if {[regexp {^WARNING: The domain name, [^,]*, does not match the DNS name\(s\) on the server certificate:} $line]} { +- set skip 1 ++ set skip_hostname_mode 1 + verbose -log "skipping: $line" + continue + } +diff --git a/testsuite/systemtap.server/server_concurrency.exp b/testsuite/systemtap.server/server_concurrency.exp +index dbacb51..a31415b 100644 +--- a/testsuite/systemtap.server/server_concurrency.exp ++++ b/testsuite/systemtap.server/server_concurrency.exp +@@ -26,7 +26,7 @@ if {! [setup_server --max-threads 6]} { + set server_port 0 + set f [open $logfile] + set matched 0 +-verbose -log "Server ouput: " ++verbose -log "Server output: " + while {1} { + set line [gets $f] + if {[eof $f]} { +@@ -34,7 +34,7 @@ while {1} { + break + } + verbose -log "$line" +- if { [regexp {^.*Using network port (\d*)$} $line matched server_port ] } { ++ if { [regexp {^.*Using network address .+:(\d+)$} $line matched server_port ] } { + close $f + break + } +-- +1.8.3.1 + diff --git a/SOURCES/rhbz1051649.2.patch b/SOURCES/rhbz1051649.2.patch new file mode 100644 index 0000000..35bed36 --- /dev/null +++ b/SOURCES/rhbz1051649.2.patch @@ -0,0 +1,63 @@ +commit b728b27964bbded79d0f8c07c0bdbf6acd8fe2db +Author: Jonathan Lebon +Date: Wed Jan 8 16:38:57 2014 -0500 + + autoreconf + +diff --git a/Makefile.in b/Makefile.in +index 2c543f1..e6d03fa 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -120,8 +120,10 @@ DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/initscript/config.systemtap.in \ + $(top_srcdir)/initscript/config.stap-server.in \ + $(top_srcdir)/initscript/systemtap.in \ +- $(top_srcdir)/initscript/stap-server.in $(srcdir)/run-stap.in \ +- $(srcdir)/dtrace.in $(top_srcdir)/staprun/guest/stapshd.in \ ++ $(top_srcdir)/initscript/stap-server.in \ ++ $(top_srcdir)/initscript/99stap/module-setup.sh.in \ ++ $(srcdir)/run-stap.in $(srcdir)/dtrace.in \ ++ $(top_srcdir)/staprun/guest/stapshd.in \ + $(top_srcdir)/staprun/guest/stapsh-daemon.in \ + $(top_srcdir)/staprun/guest/stapsh@.service.in depcomp \ + $(am__noinst_HEADERS_DIST) $(oldinclude_HEADERS) +@@ -139,7 +141,8 @@ mkinstalldirs = $(install_sh) -d + CONFIG_HEADER = config.h + CONFIG_CLEAN_FILES = includes/sys/sdt-config.h \ + initscript/config.systemtap initscript/config.stap-server \ +- initscript/systemtap initscript/stap-server run-stap dtrace \ ++ initscript/systemtap initscript/stap-server \ ++ initscript/99stap/module-setup.sh run-stap dtrace \ + staprun/guest/stapshd staprun/guest/stapsh-daemon \ + staprun/guest/stapsh@.service + CONFIG_CLEAN_VPATH_FILES = +@@ -724,6 +727,8 @@ initscript/systemtap: $(top_builddir)/config.status $(top_srcdir)/initscript/sys + cd $(top_builddir) && $(SHELL) ./config.status $@ + initscript/stap-server: $(top_builddir)/config.status $(top_srcdir)/initscript/stap-server.in + cd $(top_builddir) && $(SHELL) ./config.status $@ ++initscript/99stap/module-setup.sh: $(top_builddir)/config.status $(top_srcdir)/initscript/99stap/module-setup.sh.in ++ cd $(top_builddir) && $(SHELL) ./config.status $@ + run-stap: $(top_builddir)/config.status $(srcdir)/run-stap.in + cd $(top_builddir) && $(SHELL) ./config.status $@ + dtrace: $(top_builddir)/config.status $(srcdir)/dtrace.in +diff --git a/configure b/configure +index af7c03a..69231af 100755 +--- a/configure ++++ b/configure +@@ -11420,7 +11420,7 @@ STAP_PREFIX="$stap_prefix" + + ac_config_headers="$ac_config_headers config.h:config.in" + +-ac_config_files="$ac_config_files Makefile doc/Makefile man/Makefile doc/beginners/Makefile doc/SystemTap_Tapset_Reference/Makefile man/stappaths.7 initscript/config.systemtap initscript/config.stap-server initscript/systemtap initscript/stap-server" ++ac_config_files="$ac_config_files Makefile doc/Makefile man/Makefile doc/beginners/Makefile doc/SystemTap_Tapset_Reference/Makefile man/stappaths.7 initscript/config.systemtap initscript/config.stap-server initscript/systemtap initscript/stap-server initscript/99stap/module-setup.sh" + + + +@@ -12296,6 +12296,7 @@ do + "initscript/config.stap-server") CONFIG_FILES="$CONFIG_FILES initscript/config.stap-server" ;; + "initscript/systemtap") CONFIG_FILES="$CONFIG_FILES initscript/systemtap" ;; + "initscript/stap-server") CONFIG_FILES="$CONFIG_FILES initscript/stap-server" ;; ++ "initscript/99stap/module-setup.sh") CONFIG_FILES="$CONFIG_FILES initscript/99stap/module-setup.sh" ;; + "run-stap") CONFIG_FILES="$CONFIG_FILES run-stap" ;; + "dtrace") CONFIG_FILES="$CONFIG_FILES dtrace" ;; + "stapdyn/Makefile") CONFIG_FILES="$CONFIG_FILES stapdyn/Makefile" ;; diff --git a/SOURCES/rhbz1051649.3.patch b/SOURCES/rhbz1051649.3.patch new file mode 100644 index 0000000..47e4fce --- /dev/null +++ b/SOURCES/rhbz1051649.3.patch @@ -0,0 +1,990 @@ +From f19a1ef476349c42861cfecf6dc5afdbedc9191f Mon Sep 17 00:00:00 2001 +From: Jonathan Lebon +Date: Mon, 10 Feb 2014 10:20:56 -0500 +Subject: [PATCH] man/systemtap.8.in: new man page to replace README + +This man page replaces the README.systemtap text file. The content is +almost the same. A lot of rephrasing, some restructuring, and some +clarifications that weren't present in the original document. + +- man/systemtap.8.in: new man page +- initscript/README.systemtap: remove it +- initscript/systemtap.in: add hint to man page + +- configure.ac: add man/systemtap.8.in in AC_CONFIG_FILES macro +- man/Makefile.am: add systemtap.8 to man_MANS +- systemtap.spec: replace README by man page in systemtap-initscript pkg + $files list +--- + configure.ac | 2 +- + initscript/README.systemtap | 447 -------------------------------------------- + initscript/systemtap.in | 4 +- + man/Makefile.am | 2 +- + man/systemtap.8.in | 439 +++++++++++++++++++++++++++++++++++++++++++ + systemtap.spec | 2 +- + 6 files changed, 445 insertions(+), 451 deletions(-) + delete mode 100644 initscript/README.systemtap + create mode 100644 man/systemtap.8.in + +diff --git a/configure.ac b/configure.ac +index 3f22549..9cc1e50 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -682,7 +682,7 @@ AC_SUBST(STAP_PREFIX, "$stap_prefix") + AC_CONFIG_HEADERS([config.h:config.in]) + AC_CONFIG_FILES([Makefile doc/Makefile man/Makefile \ + doc/beginners/Makefile doc/SystemTap_Tapset_Reference/Makefile \ +-man/stappaths.7 \ ++man/stappaths.7 man/systemtap.8 \ + initscript/config.systemtap initscript/config.stap-server \ + initscript/systemtap initscript/stap-server \ + initscript/99stap/module-setup.sh ]) +diff --git a/initscript/README.systemtap b/initscript/README.systemtap +deleted file mode 100644 +index 9dd1ee6..0000000 +--- a/initscript/README.systemtap ++++ /dev/null +@@ -1,447 +0,0 @@ +-Systemtap initscript +-Version 0.2.1 +-Author: Masami Hiramatsu +- +-INDEX +-===== +-1. Introduction +-2. Usage +-3. Files +-4. Configuration Format +-5. How to use +- +-1. Introduction +-=============== +-Systemtap initscript aims to provide +-- running systemtap script as a service with dependency. +-- easy way to control(start/stop) those scripts individually. +-The dependency means that which user-defined systemtap script is required by +-other script (Here the scripts don't include tapsets). This dependency +-will be useful for users who use -DRELAY_HOST and -DRELAY_GUEST. +- +-2. Usage +-======== +-2.1 Synopsis +- +-/sbin/service systemtap {start|stop|restart|status|compile|onboot|cleanup} \ +- [-r kernelrelease] [-o path.img] [-b] [-c config] [-R] [-y] [script(s)] +- +-2.2 Commands +- You have to specify one of the below commands. +- +-2.2.1 start +- Run script(s). If the script(s) is already started, the command will be +- ignored. If it fails to start, return FAIL. If AUTOCOMPILE option is 'yes' +- (see 4.1.9), this will try to compile or update the specified script when +- one of the below condition is true. +- - compiled cache file does not exist. +- - mtime (modified time stamp) of original script file is newer than compiled +- script cache. +- - script options which is used when compiling(see 4.2.1) has been changed. +- - result of `uname -a` has been changed. +- If no scripts specified from command line, it starts all scripts in the script +- directory or the scripts specified by DEFAULT_START in config (see 4.1.10). +- +-2.2.2 stop +- Stop script(s). If the script(s) is already stopped, this will be ignored. +- If it fails to stop, return FAIL. +- If no scripts specified from command line, it stops all running scripts. +- +-2.2.3 restart +- Stop and start script(s) again. +- +-2.2.4 status +- Show running script(s) status and dependency. +- +-2.2.5 compile +- Compile script(s) on the specified kernel. This command takes '-r' option +- which specifies the release of the kernel(see 2.3.4) on which you would +- like to compile script(s). This command asks user whether it can overwrite +- existing caches. +- +-2.2.6 onboot +- Make script(s) part of the initramfs so that they are started earlier during +- the boot process. Only works on dracut-based systems. This command also takes +- the '-r' option. If '-r' is omitted, the initramfs is created for the running +- kernel. If '-o path.img' is given, the initramfs is created at 'path.img' (must +- be an absolute path). Otherwise, defaults to '/boot/initramfs-KVER.img', where +- KVER is `uname -r` if the '-r' option is omitted, or the given kernel version +- otherwise. +- +- If the output file already exists, it is overwritten, unless the -b switch is +- given, in which case the file is appended '.bak' rather than overwritten. Note +- however that if a '.bak' version already exists, it will not be overwritten. +- +- If no scripts are specified on the command-line, the initramfs will be created +- without including any scripts at all (i.e. no extra systemtap files added). +- +- Warning: do not use the stap -o option with onboot scripts because the +- script is started before the root filesystem is even mounted. Increase the +- buffer size if more space is needed. +- +-2.2.7 cleanup +- Cleanup compiled script(s) from cache directory(see 3.4). This command also +- takes '-r' option. If '-r' option is omitted, cleanup all caches for running +- kernel. This command asks user whether it can remove caches. +- +-2.3 Options +- Systemtap initscript can have some options. However, since user can't pass +- these options on boot, these options are only for testing or managing scripts +- after booting. +- +-2.3.1 -c config_path +- You can specify configuration path of this initscript. +- +-2.3.2 script(s) +- You can specify individual scripts to the commands. If you omit to specify +- any script, systemtap initscript will execute the command with all scripts +- in the script directory (except 'start', 'stop', and 'onboot' commands, see +- 2.2.1, 2.2.2, and 2.2.6). +- +-2.3.3 -R +- If this option is specified, systemtap initscript will try to solve +- dependency of specified script(s). This option is always set if you don't +- specify any script(s) from command line. +- +-2.3.4 -r kernelrelease +- You can specify release version of the kernel(e.g. 2.6.26.1). This option +- is valid only with compile, onboot, and cleanup commands. +- +-2.3.5 -y +- Answer yes for all questions. +- +-2.3.6 -o path.img +- Specify the path of the initramfs image. Otherwise, the default is +- '/boot/initramfs-KVER.img', where KVER is `uname -r` if the '-r' option is +- omitted, or the given kernel version otherwise. This option is only valid with +- the onboot command. +- +-2.3.7 -b +- If present, will backup an existing initramfs image by renaming it with a +- '.bak' extension. Otherwise, the initramfs is overwritten without backing up. +- This option is only valid with the onboot command. +- +-2.4 Misc +-2.4.1 Service Priority +- Each initscript has execution priority. Since user would like to trace +- other services by using systemtap, systemtap initscript should have the +- highest priority. +- +-3. Files +-======== +-3.1 initscript +- /etc/init.d/systemtap +- +- This file is an executable bash script. +- +-3.2 Configurations +- Configuration files are written in bash script. +- +-3.2.1 Global config file +- /etc/systemtap/config +- +- This config file is for global parameters(see 4.1). +- +-3.2.2 Script config files +- /etc/systemtap/conf.d/*.conf +- +- The config files under this directory are for each scripts or script groups +- (see 4.2). +- +-3.3 Script directory +- /etc/systemtap/script.d/ +- +- Systemtap initscript finds systemtap scripts from this directory. +- +-3.3.1 Scripts in the directory +- /etc/systemtap/script.d/.stp +- +- Systemtap scripts stored in the script directory must have ".stp" suffix. +- +-3.4 Cache directory +- /var/cache/systemtap// +- +- Systemtap initscript stores compiled scripts in this directory. +- +-3.4.1 Compiled scripts (or script caches) +- /var/cache/systemtap//.ko +- /var/cache/systemtap//.opts +- +- *.ko file is the compiled script, and *.opts is the file which stores +- stap options and uname -a. +- +-3.5 Message Log +- /var/log/systemtap.log +- +- All messages including compilation errors and detailed messages are sent +- to this file. +- Some error and warning messages are also sent to console and syslogd (syslog +- output is optional, because this service will start before syslog). +- +-3.6 Status files +- /var/run/systemtap/ +- +-3.7 Dracut +- Files related to dracut/initramfs creation +- +-3.7.1 Dracut stap module directory +- /usr/lib/dracut/modules.d/99stap +- +- These files permit SystemTap modules to be included in the initramfs. +- +-4. Configuration Format +-======================= +-Configuration file allows us +-- specifying options for each script +-- supporting flight recorder mode (on file or memory) +- +-4.1 Global Parameters +- +-4.1.1 SCRIPT_PATH +- Specify the absolute path of the script directory. +- (default: /etc/systemtap/script.d) +- +-4.1.2 CONFIG_PATH +- Specify the absolute path of the script config directory. +- (default: /etc/systemtap/conf.d) +- +-4.1.3 CACHE_PATH +- Specify the absolute path of the parent directory of the cache directory. +- (default: /var/cache/systemtap) +- +-4.1.4 TEMP_PATH +- Specify the absolute path of the temporary directory on which systemtap +- initscript make temporary directories to compile scripts. +- (default: /tmp) +- +-4.1.5 STAT_PATH +- Specify the absolute path of the running status directory. +- (default: /var/run/systemtap) +- +-4.1.6 LOG_FILE +- Specify the absolute path of the log file +- (default: /var/log/systemtap.log) +- +-4.1.7 PASSALL +- If this is set 'yes', systemtap initscript will fail when it fails +- to run one of the scripts. If not, systemtap initscript will not +- fail(just warn). +- (default: yes) +- +-4.1.8 RECURSIVE +- If this is set 'yes', systemtap initscript will always follow script +- dependencies. This means, you don't need to specify '-R' option. This flag is +- effective only if you specify script(s) from command line. +- (default: no) +- +-4.1.9 AUTOCOMPILE +- If this is set 'yes', systemtap initscript automatically tries to compile +- specified script if there is no valid cache. Otherwise, it just fails to +- run script(s). +- (default: yes) +- +-4.1.10 DEFAULT_START +- Specify scripts which will be started by default. If omitted (or empty), +- all scripts in the script directory will be started. +- (default: "") +- +-4.1.11 ALLOW_CACHEONLY +- If this is set 'yes', systemtap initscript list up cache-only scripts too. +- *NOTE*: systemtap initscript will load unexpected obsolete caches with this +- option. You should check cache directory before enabling this option. +- (default: no) +- +-4.1.12 LOG_BOOT_ERR +- Because boot-time scripts are run before the root filesystem is mounted, +- staprun's stderr cannot be logged to the LOG_FILE as usual (see 4.1.6). +- However, the log can instead be output to /var/run/systemtap/$script.log (which +- is accessible at boot-time) by setting LOG_BOOT_ERR to 'yes'. If STAT_PATH is +- different from the default, the log files will be moved there upon executing +- any of the initscript commands. +- +-4.2 Script Parameters +- +-4.2.1 _OPT +- Specify options passed to stap command for each script. "script-name" is the +- name of the script file without the suffix extension(.stp). +- Some options are just ignored. And even if you don't specify -F option, +- systemtap initscript always add it for flight recorder mode. +- - Below options are ignored when compiling script. +- -p,-m,-r,-c,-x,-e,-s,-o,-h,-V,-k +- - Below options are ignored when starting script. +- -h,-V,-v,-t,-p,-I,-e,-R,-r,-m,-k,-g,-P,-D,-b,-u,-q,-w,-l,-d,-L,-F, and +- other long options. +- +-4.2.2 _REQ +- Specify script dependency(which script this script requires). +- For example, "foo.stp" script requires(or run after) "bar.stp" script, set +- +- foo_REQ="bar" +- +- If the script requires many scripts, set all scripts separated by spaces. +- +- foo_REQ="bar baz" +- +-4.3 Configuration Example +- +-4.3.1 Global Config Example +---- +-SCRIPT_PATH=/var/systemtap/script.d/ +-PASSALL=yes +-RECURSIVE=no +---- +- +-4.3.2 Script Config Example +---- +-script1_OPT="-o /var/log/script1.out -DRELAYHOST=group1" +-script2_OPT="-DRELAYGUEST=group1" +-script2_REQ=script1 +---- +- +-5. How to use +-============= +- +-5.1 Package Installation +- After installing systemtap package, install systemtap-initscript package. +- # yum install systemtap-initscript +- This package will include initscript and default configuration file and +- other files. +- +-5.2 Script installation +-5.2.1 Installing script files +- Copy a systemtap script ("script1.stp") into script directory. +- # cp script1.stp /etc/systemtap/script.d/ +- +-5.2.2 Configuration script options +- Add configuration file to specify options. +- # vi /etc/systemtap/conf.d/group1 +- script1_OPT="-o /var/log/group1.log -DRELAYHOST=group1" +- +-5.2.3 Installing script file with dependency +- For example, a script("script2.stp") which shares buffer with another +- script("script1.stp"), there is a dependency. In this case, you just do +- as following. +- +- # cp script2.stp /etc/systemtap/script.d/ +- # vi /etc/systemtap/conf.d/group1 +- script2_OPT="-DRELAYGUEST=group1" +- script2_REQ=script1 +- +- In this case, if stap fails to run script1.stp, systemtap initscript will +- not run script2.stp. +- +-5.3 Testing +- After installing all scripts, please make sure to run service successfully. +- # service systemtap start +- # service systemtap stop +- If there is no error, we are ready to use it. +- +-5.4 Service Enabling +- After all test passed, enable systemtap initscript. +- # chkconfig systemtap on +- +-5.5 Adding script +-5.5.1 Installing and configuring new scripts +- Copy new systemtap script("script3.stp") into script directory. +- # cp script3.stp /etc/systemtap/script.d/ +- and configure it. +- # vi /etc/systemtap/conf.d/group1 +- script3_OPT="-DRELAYGUEST=group1" +- script3_REQ="script1" +- +-5.5.2 Start new script +- If you've already started systemtap initscript, just start new script. +- # service systemtap start script3 +- +-5.6 Deleting script +-5.6.1 Deleting old script +- Remove old script ("script2.stp") and remove configure lines +- # rm /etc/systemtap/script.d/script2.stp +- # vi /etc/systemtap/conf.d/group1 +- (delete script2_OPT and script2_REQ) +- +-5.6.2 Stopping old script and cleanup +- Stop old script. +- # service systemtap stop script2 +- And cleanup the script caches. +- # service systemtap cleanup script2 +- +-5.7 Updating kernel +- Usually, you don't need to do anything. Systemtap initscript checks the +- kernel version when starting the service, and compile scripts. +- (If you would like to use compiled scripts due to lack of compiler or +- debuginfo on the system, see 5.8) +- However, if you want to avoid compiling when booting system, you can prepare +- script caches for new kernel. +- # service systemtap compile -r +- +-5.8 Using with compiled scripts +- Sometimes, production systems don't have any compilation environment. Even +- though, you can use systemtap initscript with compiled scripts as script +- caches, which are compiled on other machine (but same software environment). +- +-5.8.1 Preparing compiled scripts +- As described in 5.2, installing scripts and configure it on the compiling +- machine (which has compilation environment). +- After that, compile those scripts. +- # service systemtap compile -r +- And package the compiled scripts and configuration file. +- # tar czf stap-scripts-.tar.gz \ +- /var/cache/systemtap/ /etc/systemtap/conf.d/ +- And copy this package to the target machine. +- +-5.8.2 Installing pre-compiled scripts +- On the target machine, unpackage the compiled scripts into cache +- directory. +- # tar xzf stap-scripts-.tar.gz -C /var/cache/systemtap/ +- # mv /var/cache/systemtap/ /etc/systemtap/conf.d/ +- At last, set AUTOCOMPILE=no and ALLOW_CACHEONLY=yes in config file. +- # vi /etc/systemtap/config +- AUTOCOMPILE=no +- ALLOW_CACHEONLY=yes +- +-5.9 Starting scripts during early-boot +- The initscript also allows you to start scripts earlier during the boot +- process by creating an initramfs containing the script's module. Your system +- must be dracut-based for this to work. Starting at this stage gives access to +- information otherwise very hard to obtain. +- +-5.9.1 Preparing the script +- As usual, place the script in /etc/systemtap/script.d and any configuration +- settings in /etc/systemtap/conf.d. (Note however that -o and -c are not +- supported). +- +-5.9.2 Adding to initramfs +- Simply run the command: +- # service systemtap onboot my_script +- If the script is not already compiled and cached, it will be done at this +- point. A new initramfs will then be created at the default location. You can +- specify the '-b' option to make sure that your current initramfs is backed up. +- You can then restart your system. See 2.2.6 for more information regarding the +- onboot command. +- +-5.9.3 Adding to a different initramfs +- Rather than taking the spot of the default initramfs, you may want to create a +- different initramfs for a one-time boot. You can do this using the -o option: +- # service systemtap onboot -o /boot/special_initramfs.img +- Once the initramfs is created, you can change the command-line options at +- boot-time so that the new image is used rather than the usual one. +- +-5.9.4 Creating an initramfs for a different kernel +- Just like the compile command, you can use the -r option to specify the kernel +- for which you would like to create the initramfs. This is useful when you are +- about to upgrade and would like to prepare in advance. For example: +- # service systemtap onboot -r 3.12.6-200.fc19.x86_64 my_script +- +-5.9.5 Removing from initramfs +- To remove all scripts from the initramfs, you can run: +- # service systemtap onboot +- (That is, without any scripts explicitly mentioned). This will simply create +- a standard initramfs without any SystemTap modules inserted. +- +-5.9.6 Troubleshooting +- There can be many reasons for which the module didn't insert or did not work as +- expected. It may be useful to turn on dracut debugging by adding 'rdinitdebug' to +- the kernel command-line and checking dmesg/journalctl -ae. Also, you can +- capture the stderr output of staprun by setting LOG_BOOT_ERR to 'yes' (see +- 4.1.12). +diff --git a/initscript/systemtap.in b/initscript/systemtap.in +index 5290f56..21f9018 100755 +--- a/initscript/systemtap.in ++++ b/initscript/systemtap.in +@@ -83,7 +83,7 @@ INITRAMFS= + BACKUP_INITRAMFS= + + echo_usage () { +- echo $"Usage: $prog {start|stop|status|restart|compile|onboot|cleanup|condrestart|try-restart|reload|force-reload} [option]" ++ echo $"Usage: $prog {start|stop|status|restart|compile|onboot|cleanup|condrestart|try-restart|reload|force-reload} [OPTIONS] [SCRIPTS]" + echo $"Options:" + echo $" -b : backup initramfs before overwriting" + echo $" -c configfile : specify config file" +@@ -92,6 +92,8 @@ echo_usage () { + echo $" -R : recursively dependency checking" + echo $" -y : answer yes for all questions" + echo $" script(s) : specify systemtap scripts" ++ echo $"" ++ echo $"See systemtap(8) for full documentation" + } + + #----------------------------------------------------------------- +diff --git a/man/Makefile.am b/man/Makefile.am +index b626481..ef0892e 100644 +--- a/man/Makefile.am ++++ b/man/Makefile.am +@@ -4,7 +4,7 @@ + AUTOMAKE_OPTIONS = no-dist foreign + + man_MANS = stapprobes.3stap stapfuncs.3stap stapvars.3stap stapex.3stap \ +- dtrace.1 stap-merge.1 stappaths.7 stapsh.8 ++ dtrace.1 stap-merge.1 stappaths.7 stapsh.8 systemtap.8 + + # NB: this doesn't work, apparently because make doesn't like + # file names with :: in them, misinterpreting them as some kind +diff --git a/man/systemtap.8.in b/man/systemtap.8.in +new file mode 100644 +index 0000000..cea3868 +--- /dev/null ++++ b/man/systemtap.8.in +@@ -0,0 +1,439 @@ ++.\" -*- nroff -*- ++.TH SYSTEMTAP 8 ++.SH NAME ++systemtap \- SystemTap initscript service ++ ++.\" macros ++.de SAMPLE ++ ++.nr oldin \\n(.i ++.br ++.RS ++.nf ++.nh ++.. ++.de ESAMPLE ++.hy ++.fi ++.RE ++.in \\n[oldin]u ++ ++.. ++ ++.SH SYNOPSIS ++.B service systemtap ++.IR COMMAND " [" OPTIONS "] [" SCRIPT ...] ++ ++.SH DESCRIPTION ++The SystemTap initscript aims to provide a way to run scripts as a service and ++easily control them individually. Scripts can be configured to start upon manual ++request, or during system startup. On dracut-based systems, it is also possible ++to integrate scripts in the initramfs and have them start during early-boot. ++ ++There are various parameters and options available to modify global behaviour, ++as well as script behaviour. Dependencies between scripts can be established so ++that starting one starts others (especially convenient when using the ++-DRELAY_HOST and -DRELAY_GUEST options of \fIstap\fR(1)). ++ ++The configuration file of the initscript is located at ++\fB@sysconfdir@/systemtap/config\fR. Acceptable parameters are detailed in the ++GLOBAL PARAMETERS section. ++ ++Scripts must be placed in the \fB@sysconfdir@/systemtap/script.d\fR directory ++and must have a \fB.stp\fR extension. When referring to them on the command-line ++however, there in no need to include the \fB.stp\fR extension. The scripts ++directory may be changed by setting the SCRIPT_PATH parameter in the ++configuration file. ++ ++.SH COMMANDS ++One of the commands below must be specified: ++ ++.TP ++.B start ++Start \fISCRIPT\fRs. If no scripts are specified, start the scripts specified by ++the DEFAULT_START configuration. If DEFAULT_START is not set, start all scripts ++in the script directory. For scripts already started, the command is ignored. ++The command will fail if the scripts fail to start (see also the PASSALL ++configuration). ++ ++If the AUTOCOMPILE configuration is on, the command will try to compile or ++update the specified scripts when one of the below conditions is true: ++.RS ++.IP - 2 ++The compiled cache file does not exist. ++.IP - ++The mtime (modified timestamp) of the original script file is newer than the ++time of the compiled script cache. ++.IP - ++The specified stap options used to compile the script has been changed (see ++also the SCRIPT PARAMETERS section). ++.IP - ++The result of `uname -a` has been changed. ++.RE ++ ++.TP ++.B stop ++Stop \fISCRIPT\fRs. If no scripts are specified, stop all running scripts. For ++scripts already stopped, the command is ignored. The command will fail if the ++scripts fail to stop (see also the PASSALL configuration). ++ ++.TP ++.B restart ++Stop and start \fISCRIPT\fRs. ++ ++.TP ++.B status ++Show the state of \fISCRIPT\fRs and their dependencies. ++ ++.TP ++.B compile ++Compile \fISCRIPT\fRs but do not start them. If the scripts have already been ++compiled, prompt for confirmation before overwriting cache. Compile for the ++current kernel, or the kernel release specified by the \fB-r\fR option. ++ ++.TP ++.B onboot ++Make \fISCRIPT\fRs part of the initramfs so that they are started earlier during ++the boot process. This command is only available on dracut-based systems. If no ++scripts are specified, create a normal initramfs devoid of any SystemTap files. ++ ++The initramfs is created for the current kernel, or the kernel release specified ++by the \fB-r\fR option. The path of the created initramfs defaults ++to \fB/boot/initramfs-KVER.img\fR, where KVER is the output of `uname -r`. Use ++the \fB-o\fR option to specify a different path. ++ ++If the output file already exists, it is overwritten, unless the \fB-b\fR switch ++is given, in which case the file is appended \fB.bak\fR rather than overwritten. ++However, if there is already a \fB.bak\fR version of the file, the backup will ++not be overwritten. ++ ++WARNING: do not use the \fB-o\fR option of \fIstap\fR(1) with onboot scripts ++because the script is started before the root filesystem is even mounted. ++Increase the buffer size if more space is needed. ++ ++.TP ++.B cleanup ++Delete the compiled \fISCRIPT\fRs from cache. If no scripts are specified, then ++all compiled scripts are deleted. Only the cache for the current kernel is ++deleted, or the kernel release specified by the \fB-r\fR option. Prompt for ++confirmation before deleting. ++ ++.SH OPTIONS ++Many of the commands can also take options. However, since users can't pass ++these options on boot, they are only meant for managing scripts after boot and ++for testing. Available options are: ++ ++.TP ++.BI "-c " CONFIG_FILE ++Specify a different configuration file in place of the default one. ++ ++.TP ++.B -R ++When using the \fBstart\fR and \fBstop\fR commands, also include the scripts' ++dependencies (recursively). ++ ++.TP ++.BI "-r " KERNEL_RELEASE ++When using the \fBcompile\fR, \fBonboot\fR, and \fBcleanup\fR commands, specify ++the target kernel version rather than using the current one. Must be in the same ++format as `uname -r`. ++ ++.TP ++.B -y ++Answer yes for all prompts. ++ ++.TP ++.BI "-o " PATH.IMG ++When using the \fBonboot\fR command, specify the output path of the created ++initramfs. ++ ++.TP ++.B -b ++When using the \fBonboot\fR command, backup an existing initramfs image by ++adding a \fB.bak\fR extension rather than overwriting it. Without this option, ++the initramfs is overwritten. ++ ++.SH GLOBAL PARAMETERS ++These parameters affect the general behaviour of the SystemTap initscript ++service. They can be specified in the configuration file. ++ ++.TP ++.B SCRIPT_PATH ++Specify the absolute path of the script directory. These are the scripts on ++which the initscript can operate. Scripts must have the \fB.stp\fR extension. ++The default path is \fB@sysconfdir@/systemtap/script.d\fR. ++ ++.TP ++.B CONFIG_PATH ++Specify the absolute path of the script configuration directory. These ++configuration files contain options for specific scripts. They must have the ++\fB.conf\fR extension. The default path is \fB@sysconfdir@/systemtap/conf.d\fR. ++ ++.TP ++.B CACHE_PATH ++Specify the absolute path of the cache directory. The default path is ++\fB@localstatedir@/cache/systemtap\fR. ++ ++.TP ++.B TEMP_PATH ++Specify the absolute path of the temporary directory in which SystemTap ++makes temporary directories to compile scripts. The default path is \fB/tmp\fR. ++ ++.TP ++.B STAT_PATH ++Specify the absolute path of the directory containing PID files used to track ++the status of SystemTap scripts. The default path is ++\fB@localstatedir@/run/systemtap\fR. ++ ++.TP ++.B LOG_FILE ++Specify the absolute path of the log file. All messages are sent to this file, ++including compilation and runtime errors. The default path is ++\fB@localstatedir@/log/systemtap.log\fR. ++ ++.TP ++.B PASSALL ++If this is set \fByes\fR, initscript commands that operate on multiple scripts ++will report as failed when the action could not be performed on at least one ++script. If set to \fBno\fR, only a warning is emitted. The default is \fByes\fR. ++ ++.TP ++.B RECURSIVE ++If this is set \fByes\fR, the initscript will always follow script dependencies ++recursively. This means that there is no need to specify the \fB-R\fR option. ++This flag is effective only if you specify script(s) from the command-line. The ++default is \fBno\fR. ++ ++.TP ++.B AUTOCOMPILE ++If this is set \fByes\fR, the initscript automatically tries to compile ++specified scripts when needed if there is no valid cache. Otherwise, the related ++command simply fails. The default is \fByes\fR. ++ ++.TP ++.B DEFAULT_START ++Specify scripts which will be started by default. If omitted (or empty), all ++scripts in the script directory will be started. The default is \fB""\fR. ++ ++.TP ++.B ALLOW_CACHEONLY ++If this is set \fByes\fR, the initscript will also allow operating on scripts ++that are located in the cache directory, but not in the script directory. The ++default is \fBno\fR. ++ ++WARNING: the initscript may load unexpected obsolete caches with this option. ++The cache directory should be checked before enabling this option. ++ ++.TP ++.B LOG_BOOT_ERR ++Because boot-time scripts are run before the root filesystem is mounted, ++staprun's stderr cannot be logged to the LOG_FILE as usual. However, the log ++can instead be output to /var/run/systemtap/$script.log by setting LOG_BOOT_ERR ++to \fByes\fR. If STAT_PATH is different from the default, the log files will be ++moved there upon executing any of the initscript commands. The default is ++\fBno\fR. ++ ++.PP ++Here is a global configuration file example: ++.SAMPLE ++SCRIPT_PATH=/var/systemtap/script.d/ ++PASSALL=yes ++RECURSIVE=no ++.ESAMPLE ++ ++.SH SCRIPT PARAMETERS ++These parameters affect the compilation or runtime behaviour of specific ++SystemTap scripts. They must be placed in config files located in the ++CONFIG_PATH directory. ++ ++.TP ++.B