@@ -2293,6 +2293,77 @@ bool MYSQL_LOG::init_and_set_log_file_name(const char *log_name,
22932293}
22942294
22952295
2296+ bool is_valid_log_name (const char *name, size_t len)
2297+ {
2298+ if (len > 3 )
2299+ {
2300+ const char *tail= name + len - 4 ;
2301+ if (my_strcasecmp (system_charset_info, tail, " .ini" ) == 0 ||
2302+ my_strcasecmp (system_charset_info, tail, " .cnf" ) == 0 )
2303+ {
2304+ return false ;
2305+ }
2306+ }
2307+ return true ;
2308+ }
2309+
2310+
2311+ /* *
2312+ Get the real log file name, and possibly reopen file.
2313+
2314+ Use realpath() to get the path with symbolic links
2315+ expanded. Then, close the file, and reopen the real path using the
2316+ O_NOFOLLOW flag. This will reject following symbolic links.
2317+
2318+ @param file File descriptor.
2319+ @param log_file_key Key for P_S instrumentation.
2320+ @param open_flags Flags to use for opening the file.
2321+ @param opened_file_name Name of the open fd.
2322+
2323+ @retval file descriptor to open file with 'real_file_name', or '-1'
2324+ in case of errors.
2325+ */
2326+
2327+ #ifndef _WIN32
2328+ static File mysql_file_real_name_reopen (File file,
2329+ #ifdef HAVE_PSI_INTERFACE
2330+ PSI_file_key log_file_key,
2331+ #endif
2332+ int open_flags,
2333+ const char *opened_file_name)
2334+ {
2335+ DBUG_ASSERT (file);
2336+ DBUG_ASSERT (opened_file_name);
2337+
2338+ /* Buffer for realpath must have capacity for PATH_MAX. */
2339+ char real_file_name[PATH_MAX];
2340+
2341+ /* Get realpath, validate, open realpath with O_NOFOLLOW. */
2342+ if (realpath (opened_file_name, real_file_name) == NULL )
2343+ {
2344+ (void ) mysql_file_close (file, MYF (0 ));
2345+ return -1 ;
2346+ }
2347+
2348+ if (mysql_file_close (file, MYF (0 )))
2349+ return -1 ;
2350+
2351+ if (strlen (real_file_name) > FN_REFLEN)
2352+ return -1 ;
2353+
2354+ if (!is_valid_log_name (real_file_name, strlen (real_file_name)))
2355+ {
2356+ sql_print_error (" Invalid log file name after expanding symlinks: '%s'" ,
2357+ real_file_name);
2358+ return -1 ;
2359+ }
2360+
2361+ return mysql_file_open (log_file_key, real_file_name,
2362+ open_flags | O_NOFOLLOW,
2363+ MYF (MY_WME | ME_WAITTANG));
2364+ }
2365+ #endif // _WIN32
2366+
22962367/*
22972368 Open a (new) log file.
22982369
@@ -2358,8 +2429,22 @@ bool MYSQL_LOG::open(
23582429
23592430 if ((file= mysql_file_open (log_file_key,
23602431 log_file_name, open_flags,
2361- MYF (MY_WME | ME_WAITTANG))) < 0 ||
2362- init_io_cache (&log_file, file, IO_SIZE, io_cache_type,
2432+ MYF (MY_WME | ME_WAITTANG))) < 0 )
2433+ goto err;
2434+
2435+ #ifndef _WIN32
2436+ /* Reopen and validate path. */
2437+ if ((log_type_arg == LOG_UNKNOWN || log_type_arg == LOG_NORMAL) &&
2438+ (file= mysql_file_real_name_reopen (file,
2439+ #ifdef HAVE_PSI_INTERFACE
2440+ log_file_key,
2441+ #endif
2442+ open_flags,
2443+ log_file_name)) < 0 )
2444+ goto err;
2445+ #endif // _WIN32
2446+
2447+ if (init_io_cache (&log_file, file, IO_SIZE, io_cache_type,
23632448 mysql_file_tell (file, MYF (MY_WME)), 0 ,
23642449 MYF (MY_WME | MY_NABP |
23652450 ((log_type == LOG_BIN) ? MY_WAIT_IF_FULL : 0 ))))
0 commit comments