Commit Graph

145 Commits

Author SHA1 Message Date
Glenn Strauss b38817b678 [core] mark attr malloc, returns nonnull
mark some core code with attributes malloc, returns nonnull
2021-09-17 05:06:16 -04:00
Glenn Strauss cd738d4daa [build] propagate HAVE_DLFCN_H in builds 2021-09-08 15:06:07 -04:00
Glenn Strauss 9a2404cec6 [core] quiet compiler warnings
cast away signedness warning in request_check_hostname()
mod_gnutls https_add_ssl_client_entries crts allocated if crt_size != 0
  (which is already checked earlier in routine)

report from FaceBook Infer static analysis tool (
- quiet dead store warnings
- check return != NULL from allocation funcs
2021-09-04 08:08:26 -04:00
Glenn Strauss 309c1693ac [multiple] Y2038 32-bit signed time_t mitigations
Most OS platforms have already provided solutions to
Y2038 32-bit signed time_t 5 - 10 years ago (or more!)
Notable exceptions are Linux i686 and FreeBSD i386.

Since 32-bit systems tend to be embedded systems,
and since many distros take years to pick up new software,
this commit aims to provide Y2038 mitigations for lighttpd
running on 32-bit systems with Y2038-unsafe 32-bit signed time_t

* Y2038: lighttpd 1.4.60 and later report Y2038 safety
  $ lighttpd -V
    + Y2038 support                                    # Y2038-SAFE
  $ lighttpd -V
    - Y2038 support (unsafe 32-bit signed time_t)      # Y2038-UNSAFE

* Y2038: general platform info
  * Y2038-SAFE: lighttpd 64-bit builds on platforms using 64-bit time_t
      - all major 64-bit platforms (known to this author) use 64-bit time_t
  * Y2038-SAFE: lighttpd 32-bit builds on platforms using 64-bit time_t
      - Linux x32 ABI (different from i686)
      - FreeBSD all 32-bit and 64-bit architectures *except* 32-bit i386
      - NetBSD 6.0 (released Oct 2012) all 32-bit and 64-bit architectures
      - OpenBSD 5.5 (released May 2014) all 32-bit and 64-bit architectures
      - Microsoft Windows XP and Visual Studio 2005 (? unsure ?)
        Another reference suggests Visual Studio 2015 defaults to 64-bit time_t
      - MacOS 10.15 Catalina (released 2019) drops support for 32-bit apps
  * Y2038-SAFE: lighttpd 32-bit builds on platforms using 32-bit unsigned time_t
      - e.g. OpenVMS (unknown if lighttpd builds on this platform)
  * Y2038-UNSAFE: lighttpd 32-bit builds on platforms using 32-bit signed time_t
      - Linux 32-bit (including i686)
          - glibc 32-bit library support not yet available for 64-bit time_t
              - Linux kernel 5.6 on 32-bit platforms does support 64-bit time_t
                "Note: at this point, 64-bit time support in dual-time
                 configurations is work-in-progress, so for these
                 configurations, the public API only makes the 32-bit time
                 support available. In a later change, the public API will
                 allow user code to choose the time size for a given
                 compilation unit."
              - compiling with -D_TIME_BITS=64 currently has no effect
          - glibc recent (Jul 2021) mailing list discussion
      - FreeBSD i386
      - DragonFlyBSD 32-bit

* Y2038 mitigations attempted on Y2038-UNSAFE platforms (32-bit signed time_t)
  * lighttpd prefers system monotonic clock instead of realtime clock
    in places where realtime clock is not required
  * lighttpd treats negative time_t values as after 19 Jan 2038 03:14:07 GMT
  * (lighttpd presumes that lighttpd will not encounter dates before 1970
    during normal operation.)
  * lighttpd casts struct stat st.st_mtime (and st.st_*time) through uint64_t
    to convert negative timestamps for comparisions with 64-bit timestamps
    (treating negative timestamp values as after 19 Jan 2038 03:14:07 GMT)
  * lighttpd provides unix_time64_t (int64_t) and
  * lighttpd provides struct unix_timespec64 (unix_timespec64_t)
    (struct timespec equivalent using unix_time64_t tv_sec member)
  * lighttpd provides gmtime64_r() and localtime64_r() wrappers
    for platforms 32-bit platforms using 32-bit time_t and
    lighttpd temporarily shifts the year in order to use
    gmtime_r() and localtime_r() (or gmtime() and localtime())
    from standard libraries, before readjusting year and passing
    struct tm to formatting functions such as strftime()
  * lighttpd provides TIME64_CAST() macro to cast signed 32-bit time_t to
    unsigned 32-bit and then to unix_time64_t

* Note: while lighttpd tries handle times past 19 Jan 2038 03:14:07 GMT
  on 32-bit platforms using 32-bit signed time_t, underlying libraries and
  underlying filesystems might not behave properly after 32-bit signed time_t
  overflows (19 Jan 2038 03:14:08 GMT).  If a given 32-bit OS does not work
  properly using negative time_t values, then lighttpd likely will not work
  properly on that system.

* Other references and blogs
2021-09-04 08:08:26 -04:00
Glenn Strauss d22e94ac88 [core] clear etag in stat_cache_get_entry_open()
clear etag in stat_cache_get_entry_open() after opening file
(in case a different caller used stat_get_get_entry() and then file
changed before being opened)
2021-08-27 02:16:53 -04:00
Glenn Strauss af3df29ae8 [multiple] reduce redundant NULL buffer checks
This commit is a large set of code changes and results in removal of
hundreds, perhaps thousands, of CPU instructions, a portion of which
are on hot code paths.

Most (buffer *) used by lighttpd are not NULL, especially since buffers
were inlined into numerous larger structs such as request_st and chunk.

In the small number of instances where that is not the case, a NULL
check is often performed earlier in a function where that buffer is
later used with a buffer_* func.  In the handful of cases that remained,
a NULL check was added, e.g. with r->http_host and r->conf.server_tag.

- check for empty strings at config time and set value to NULL if blank
  string will be ignored at runtime; at runtime, simple pointer check
  for NULL can be used to check for a value that has been set and is not
  blank ("")
- use buffer_is_blank() instead of buffer_string_is_empty(),
  and use buffer_is_unset() instead of buffer_is_empty(),
  where buffer is known not to be NULL so that NULL check can be skipped
- use buffer_clen() instead of buffer_string_length() when buffer is
  known not to be NULL (to avoid NULL check at runtime)
- use buffer_truncate() instead of buffer_string_set_length() to
  truncate string, and use buffer_extend() to extend

Examples where buffer known not to be NULL:
  - cpv->v.b from config_plugin_values_init is not NULL if T_CONFIG_BOOL
    (though we might set it to NULL if buffer_is_blank(cpv->v.b))
  - address of buffer is arg (&foo)
    (compiler optimizer detects this in most, but not all, cases)
  - buffer is checked for NULL earlier in func
  - buffer is accessed in same scope without a NULL check (e.g. b->ptr)

internal behavior change:
  callers must not pass a NULL buffer to some funcs.
  - buffer_init_buffer() requires non-null args
  - buffer_copy_buffer() requires non-null args
  - buffer_append_string_buffer() requires non-null args
  - buffer_string_space() requires non-null arg
2021-08-27 02:16:53 -04:00
Glenn Strauss 937d83b6cf [core] inline fam_dir_entry buffer 'name' member 2021-08-27 02:16:53 -04:00
Glenn Strauss dbe3e2361b [multiple] prefer monotonic time for internal use
Note: monotonic time does not change while VM is suspended

Continue to use real time where required by HTTP protocol, for logging
and for other user-visible instances, such as mod_status, as well as for
external databases and caches.
2021-03-11 18:59:53 -05:00
Glenn Strauss ac1fee6b30 [core] adjust stat_cache_get_entry() conditions 2021-03-07 04:38:34 -05:00
Glenn Strauss b700a8ca09 [multiple] etag.[ch] -> http_etag.[ch]; better imp
more efficient implementation of HTTP ETag generation and comparison

modify dekhash() to take hash value to allow for incremental hashing
2020-12-25 14:41:16 -05:00
Glenn Strauss 1212f60991 buffer_append_path_len() to join paths
use buffer_append_path_len() to join path segments
2020-12-24 16:13:20 -05:00
Glenn Strauss 881d05076a [core] attempt to quiet some coverity warnings 2020-12-17 04:01:34 -05:00
Glenn Strauss 1d73fc2329 [core] portability fix if st_mtime not defined 2020-12-09 17:39:43 -05:00
Glenn Strauss adf7aea0e1 [core] wrap a macro value with parens
(code review)
2020-12-08 15:17:11 -05:00
Glenn Strauss 01d49a283d [core] attempt to quiet some coverity warnings
read() on inotify fd does not return partial records,
and the info from the kernel can be trusted.  Still add a sanity check.

If initialization of inotify fails, server will subsequently exit,
so memory leak reported by coverity is insignificant.
2020-11-29 20:04:19 -05:00
Glenn Strauss 730c932e3c [multiple] more forgiving config str to boolean (fixes #3036)
more consistent use of shared code config_plugin_value_tobool()

(thx tow-conf)

  "The on/off keywords in boolean configuration options is inconsistent, which might be misleading and error-prone."
2020-11-16 01:39:14 -05:00
Glenn Strauss dce440602d [core] stat_cache preprocessor paranoia 2020-11-05 01:08:11 -05:00
Glenn Strauss 520bffcd24 [core] use struct kevent on stack in stat_cache
This alternative approach attempts to work around error:
  invalid application of 'sizeof' to incomplete type 'struct kevent'
seen in continuous integration (CI) autoconf build on FreeBSD VM
2020-11-05 00:48:41 -05:00
Glenn Strauss 0b00b13a42 [core] use kqueue() instead of FAM/gamin on *BSD
Note: there have always been limitations with lighttpd stat_cache.[ch]
using FAM/gamin on *BSD via kqueue() as lighttpd stat_cache.[ch] only
monitors directories.  This kqueue() implementation also only monitors
directories and has limitations.

lighttpd stat_cache.[ch] is notified about additions and removals of
files within a monitored directory but might not be notified of changes
such as timestamps (touch), ownership, or even changes in contents
(e.g. if a file is edited through a hard link)

server.stat-cache-engine = "disable" should be used when files should
not be cached.  Full stop.  Similarly, "disable" is recommended if files
change frequently.  If using server.stat-cache-engine with any engine,
there are caching effects and tradeoffs.

On *BSD and using kqueue() on directories, any change detected clears
the stat_cache of all entries in that directory, since monitoring only
the directory does not indicate which file was added or removed.  This
is not efficient for directories containing frequently changed files.
2020-11-04 20:16:30 -05:00
Glenn Strauss 5c7173026f [core] use inotify in stat_cache.[ch] on Linux
use inotify in stat_cache.[ch] on Linux, replacing FAM/gamin
2020-11-04 03:53:15 -05:00
Glenn Strauss af04e0b0e1 [core] silence coverity warnings (false positives) 2020-10-20 15:29:25 -04:00
Glenn Strauss 7f8ab9dd29 [core] stat_cache_entry reference counting
future: should probably create fd cache separate from stat_cache,
        perhaps along w/ http-specific fields like etag and content_type
        and maybe even mmap
2020-10-20 11:51:48 -04:00
Glenn Strauss fe02111888 [multiple] stat_cache_path_stat() for struct st
stat_cache_path_stat() for cached (struct st *)
2020-10-19 21:40:14 -04:00
Glenn Strauss d8e5e21eb7 [core] stat_cache_get_entry_open()
simple interface to cache open file by extending struct stat_cache_entry

future: should probably create fd cache separate from stat_cache,
        perhaps along w/ http-specific fields like etag and content_type
2020-10-19 21:40:14 -04:00
Glenn Strauss 7d368cd7a5 [core] stat_cache_path_isdir() 2020-10-13 22:31:07 -04:00
Glenn Strauss b7370a6d46 [core] save errno around close() if fstat() fails
(should not happen, since file was just opened)
2020-10-11 12:19:27 -04:00
Glenn Strauss 156e1da2ae [core] rename splaytree.[ch] to algo_splaytree.[ch] 2020-10-11 12:19:26 -04:00
Glenn Strauss 3e046ccabf [core] dlsym for FAMNoExists() for compat w/ fam
gamin should be used instead of fam; fam is no longer maintained

This patch makes it safe to build lighttpd with gamin, but run on
systems with the (deprecated) fam installed, which can happen due
to historical package dependency declarations on some platforms
(Debian, Ubuntu).

gamin and fam are not 100% binary compatible.
(Among other things, fam does not provide FAMNoExists())

  "llibgamin vs libfam conflict solving"
  "libgamin0: libfam shlib dependency wrongly set to libfam0"
  "undefined symbol: FAMNoExists"
2020-08-10 15:56:28 -04:00
Glenn Strauss e11514b086 [mod_auth,mod_vhostdb] add caching option (fixes #2805)
auth.cache    = ("max-age" => "600")
vhostdb.cache = ("max-age" => "600")

If specified with an empty array, default max-age is 600 secs (10 mins)
auth.cache    = ()
vhostdb.cache = ()

(Note: cache expiration occurs every 8 seconds, so maximum cache time
 might be up to max-age + 8 seconds)

  "mod_auth caching"
2020-07-13 17:39:27 -04:00
Glenn Strauss 2781a3be6d [multiple] address coverity warnings 2020-07-10 21:34:28 -04:00
Glenn Strauss f85d1f9070 [core] splaytree_djbhash() in splaytree.h (reuse)
rename and move hashme() from stat_cache.c to splaytree_djbhash() in
splaytree.h for code reuse
2020-07-10 00:02:48 -04:00
Glenn Strauss d334eaf1ee [core] uint32_t is plenty large for path names 2020-07-09 23:45:04 -04:00
Glenn Strauss 28f1867c11 quiet clang analyzer scan-build warnings
(expansion of buffer_string_lenth() inline function and CONST_BUF_LEN()
 macro, which always check for NULL, appears to cause the analyzer to
 believe that a pointer might be NULL in cases where it otherwise can
 not be NULL)

2020-07-08 22:51:32 -04:00
Glenn Strauss 455dc03778 [core] prefer getxattr() instead of get_attr()
(when lighttpd is built ./configure --with-attr)
2020-07-08 22:51:31 -04:00
Glenn Strauss abe61d0445 [core] return EINVAL if stat_cache_get_entry w/o /
return EINVAL if stat_cache_get_entry() called on path w/o leading '/'
2020-07-08 19:54:30 -04:00
Glenn Strauss c752d4696e [multiple] correct misspellings in comments
  "Script for fixing spelling errors with codespell"
2020-07-08 19:54:30 -04:00
Glenn Strauss 7c7f8c467c [multiple] split con, request (very large change)
NB: r->tmp_buf == srv->tmp_buf (pointer is copied for quicker access)

NB: request read and write chunkqueues currently point to connection
    chunkqueues; per-request and per-connection chunkqueues are
    not distinct from one another
      con->read_queue  == r->read_queue
      con->write_queue == r->write_queue

NB: in the future, a separate connection config may be needed for
    connection-level module hooks.  Similarly, might need to have
    per-request chunkqueues separate from per-connection chunkqueues.
    Should probably also have a request_reset() which is distinct from
2020-07-08 19:54:29 -04:00
Glenn Strauss 66bdd96d36 [core] isolate stat_cache subsystem
stat_cache.c no longer directly uses struct server *srv
2020-07-08 19:54:29 -04:00
Glenn Strauss 05cc88ddb4 [multiple] omit passing srv to fdevent_handler 2020-07-08 19:54:29 -04:00
Glenn Strauss 68d8d4c532 [multiple] stat_cache singleton 2020-07-08 19:54:28 -04:00
Glenn Strauss c8cd7cf49b [multiple] extern log_epoch_secs
replace srv->cur_ts
2020-07-08 19:54:28 -04:00
Glenn Strauss 409bba80b1 [multiple] reduce direct use of srv->cur_ts 2020-07-08 19:54:28 -04:00
Glenn Strauss 50bdb55de8 [multiple] connection hooks no longer get (srv *)
(explicit (server *) not passed; available in con->srv)
2020-07-08 19:54:28 -04:00
Glenn Strauss 0fcd51438d [core] create http chunk header on the stack
streamline code in http_chunk.c
2020-07-08 19:54:28 -04:00
Glenn Strauss 010c28949c [multiple] prefer (connection *) to (srv *)
convert all log_error_write() to log_error() and pass (log_error_st *)

use con->errh in preference to srv->errh (even though currently same)

avoid passing (server *) when previously used only for logging (errh)
2020-07-08 19:54:28 -04:00
Glenn Strauss 2ec70f234a [core] stat_cache_path_contains_symlink use errh
use log_error() with con->errh
2020-07-08 18:08:52 -04:00
Glenn Strauss ed62e354ff [core] use config_plugin_values_init() 2020-07-08 18:08:51 -04:00
Glenn Strauss 601c572c39 [core] inline buffer as part of data_string value
(instead of value being (buffer *))
2020-02-24 11:15:32 -05:00
Glenn Strauss ad9b7e009b [core] inline buffer as part of DATA_UNSET key
(instead of key being (buffer *))
2020-02-24 11:15:32 -05:00
Glenn Strauss 83535bbef3 [core] differentiate array_get_* for ro and rw
array_get_element_klen() is now intended for read-only access
array_get_data_unset() is used by config processing for r/w access
array_get_buf_ptr() is used for r/w access to ds->value (string buffer)
2020-02-24 11:15:32 -05:00