MCPcopy Index your code
hub / github.com/RsyncProject/rsync / change_dir

Function change_dir

util1.c:1134–1241  ·  view source on GitHub ↗

Like chdir(), but it keeps track of the current directory (in the * global "curr_dir"), and ensures that the path size doesn't overflow. * Also cleans the path using the clean_fname() function. */

Source from the content-addressed store, hash-verified

1132 * global "curr_dir"), and ensures that the path size doesn't overflow.
1133 * Also cleans the path using the clean_fname() function. */
1134int change_dir(const char *dir, int set_path_only)
1135{
1136 extern int am_daemon, am_chrooted;
1137 static int initialised, skipped_chdir;
1138 unsigned int len;
1139
1140 if (!initialised) {
1141 initialised = 1;
1142 if (getcwd(curr_dir, sizeof curr_dir - 1) == NULL) {
1143 rsyserr(FERROR, errno, "getcwd()");
1144 exit_cleanup(RERR_FILESELECT);
1145 }
1146 curr_dir_len = strlen(curr_dir);
1147 }
1148
1149 if (!dir) /* this call was probably just to initialize */
1150 return 0;
1151
1152 len = strlen(dir);
1153 if (len == 1 && *dir == '.' && (!skipped_chdir || set_path_only))
1154 return 1;
1155
1156 if (*dir == '/') {
1157 if (len >= sizeof curr_dir) {
1158 errno = ENAMETOOLONG;
1159 return 0;
1160 }
1161 if (!set_path_only && chdir(dir))
1162 return 0;
1163 skipped_chdir = set_path_only;
1164 memcpy(curr_dir, dir, len + 1);
1165 } else {
1166 unsigned int save_dir_len = curr_dir_len;
1167 if (curr_dir_len + 1 + len >= sizeof curr_dir) {
1168 errno = ENAMETOOLONG;
1169 return 0;
1170 }
1171 if (!(curr_dir_len && curr_dir[curr_dir_len-1] == '/'))
1172 curr_dir[curr_dir_len++] = '/';
1173 memcpy(curr_dir + curr_dir_len, dir, len + 1);
1174
1175 if (!set_path_only) {
1176 int chdir_failed;
1177 /* In the daemon-without-chroot deployment we must not
1178 * follow a symlink in any component of the chdir
1179 * target -- otherwise CWD escapes the module and
1180 * every subsequent path-relative syscall (open,
1181 * chmod, lchown, ...) inherits the escape, which
1182 * defeats secure_relative_open's RESOLVE_BENEATH
1183 * anchor and re-opens the CVE-2026-29518 class of
1184 * symlink TOCTOU attacks. Use the secure resolver
1185 * to get a confined dirfd, then fchdir() to it.
1186 *
1187 * If skipped_chdir is set, a previous CD_SKIP_CHDIR
1188 * call buffered an absolute prefix in curr_dir
1189 * (e.g. change_pathname's CD_SKIP_CHDIR to orig_dir)
1190 * without syncing the kernel's CWD. Resolve `dir`
1191 * relative to that prefix as basedir so the secure

Callers 7

change_pathnameFunction · 0.85
send_file_listFunction · 0.85
get_local_nameFunction · 0.85
do_server_senderFunction · 0.85
do_server_recvFunction · 0.85
mainFunction · 0.85
rsync_moduleFunction · 0.85

Calls 7

getcwdFunction · 0.85
secure_relative_openFunction · 0.85
clean_fnameFunction · 0.85
count_dir_elementsFunction · 0.85
rsyserrFunction · 0.70
rprintfFunction · 0.70
who_am_iFunction · 0.70

Tested by

no test coverage detected