Fix TOCTOU

This commit is contained in:
Martin.JM
2025-08-15 22:10:03 +02:00
parent 18651a08e7
commit e34f635943
2 changed files with 61 additions and 29 deletions
@@ -1383,10 +1383,6 @@ public class HuaweiSupportProvider {
if (dataType == -1)
return; // Empty queue
// TODO: Properly solve TOCTOU
// To make TOCTOU window smaller, set as busy
gbDevice.setBusyTask(R.string.busy_task_fetch_activity_data, context);
if (dataType == RecordedDataTypes.TYPE_ACTIVITY) {
fetchActivityData();
} else if (dataType == RecordedDataTypes.TYPE_GPS_TRACKS) {
@@ -1395,7 +1391,9 @@ public class HuaweiSupportProvider {
}
private void fetchActivityData() {
syncState.setActivitySync(true);
// Only run the sync if accepted by the sync manager
if (!syncState.startActivitySync())
return;
fetchActivityDataP2P();
int sleepStart = 0;
@@ -1449,13 +1447,13 @@ public class HuaweiSupportProvider {
@Override
public void call() {
if (!(downloadTruSleepData(start, end) && downloadStressData(start, end)))
syncState.setActivitySync(false);
syncState.stopActivitySync();
}
@Override
public void handleException(Request.ResponseParseException e) {
LOG.error("Fitness totals exception", e);
syncState.setActivitySync(false);
syncState.stopActivitySync();
}
});
@@ -1467,14 +1465,14 @@ public class HuaweiSupportProvider {
getFitnessTotalsRequest.doPerform();
} catch (IOException e) {
LOG.error("Exception on starting fitness totals request", e);
syncState.setActivitySync(false);
syncState.stopActivitySync();
}
}
@Override
public void handleException(Request.ResponseParseException e) {
LOG.error("Step data count exception", e);
syncState.setActivitySync(false);
syncState.stopActivitySync();
}
});
@@ -1485,14 +1483,14 @@ public class HuaweiSupportProvider {
getStepDataCountRequest.doPerform();
} catch (IOException e) {
LOG.error("Exception on starting step data count request", e);
syncState.setActivitySync(false);
syncState.stopActivitySync();
}
}
@Override
public void handleException(Request.ResponseParseException e) {
LOG.error("Sleep data count exception", e);
syncState.setActivitySync(false);
syncState.stopActivitySync();
}
});
@@ -1500,7 +1498,7 @@ public class HuaweiSupportProvider {
getSleepDataCountRequest.doPerform();
} catch (IOException e) {
LOG.error("Exception on starting sleep data count request", e);
syncState.setActivitySync(false);
syncState.stopActivitySync();
}
}
@@ -1520,7 +1518,8 @@ public class HuaweiSupportProvider {
}
private void fetchWorkoutData() {
syncState.setWorkoutSync(true);
if (!syncState.startWorkoutSync())
return;
int start = 0;
int end = (int) (System.currentTimeMillis() / 1000);
@@ -2894,13 +2893,13 @@ public class HuaweiSupportProvider {
}
}
syncState.setActivitySync(false);
syncState.stopActivitySync();
}
@Override
public void downloadException(HuaweiFileDownloadManager.HuaweiFileDownloadException e) {
super.downloadException(e);
syncState.setActivitySync(false);
syncState.stopActivitySync();
}
}
), true);
@@ -2924,14 +2923,14 @@ public class HuaweiSupportProvider {
if (statusData == null || statusData.length == 0) {
LOG.debug("Sleep state file empty");
syncState.setActivitySync(false);
syncState.stopActivitySync();
return;
}
HuaweiTruSleepParser.TruSleepStatus[] results = HuaweiTruSleepParser.parseState(statusData);
if (results.length == 0) {
LOG.debug("No sleep results");
syncState.setActivitySync(false);
syncState.stopActivitySync();
return;
}
for (HuaweiTruSleepParser.TruSleepStatus status : results)
@@ -2939,6 +2938,8 @@ public class HuaweiSupportProvider {
// HuaweiTruSleepParser.TruSleepData data = HuaweiTruSleepParser.parseData(sleepData);
// HuaweiTruSleepParser.analyze(this.provider, results, data);
syncState.stopActivitySync();
}
};
@@ -2987,13 +2988,13 @@ public class HuaweiSupportProvider {
} else {
LOG.debug("Stress file empty");
}
syncState.setActivitySync(false);
syncState.stopActivitySync();
}
@Override
public void downloadException(HuaweiFileDownloadManager.HuaweiFileDownloadException e) {
super.downloadException(e);
syncState.setActivitySync(false);
syncState.stopActivitySync();
}
}
), true);
@@ -3021,7 +3022,7 @@ public class HuaweiSupportProvider {
public void endOfWorkoutSync() {
this.syncState.setWorkoutSync(false);
this.syncState.stopWorkoutSync();
}
public void downloadWorkoutGpsFiles(short workoutId, Long databaseId, Runnable extraCallbackAction) {
@@ -1,5 +1,7 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei;
import android.util.Log;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -24,6 +26,10 @@ class HuaweiSyncState {
this.supportProvider = supportProvider;
}
private boolean isSyncActive() {
return !activitySync && !p2pSync && !workoutSync && workoutGpsDownload == 0;
}
public void addActivitySyncToQueue() {
LOG.debug("Add activity type to sync queue");
if (syncQueue.contains(RecordedDataTypes.TYPE_ACTIVITY))
@@ -46,10 +52,22 @@ class HuaweiSyncState {
return syncQueue.get(0);
}
public void setActivitySync(boolean state) {
LOG.debug("Set activity sync state to {}", state);
this.activitySync = state;
if (!state && !this.p2pSync) {
public boolean startActivitySync() {
synchronized(this) {
if (isSyncActive()) {
LOG.warn("Attempted to start activity sync while another sync is still active");
return false;
}
this.activitySync = true;
}
LOG.debug("Set activity sync state to true");
return true;
}
public void stopActivitySync() {
LOG.debug("Set activity sync state to false");
this.activitySync = false;
if (!p2pSync) {
this.syncQueue.remove((Integer) RecordedDataTypes.TYPE_ACTIVITY);
supportProvider.fetchRecodedDataFromQueue();
}
@@ -57,6 +75,7 @@ class HuaweiSyncState {
}
public void setP2pSync(boolean state) {
// We cannot do the syncActive check for the P2P sync as it runs in parallel with the activity sync
LOG.debug("Set p2p sync state to {}", state);
this.p2pSync = state;
if (!state && !this.activitySync) {
@@ -66,10 +85,22 @@ class HuaweiSyncState {
updateState();
}
public void setWorkoutSync(boolean state) {
LOG.debug("Set workout sync state to {}", state);
this.workoutSync = state;
if (!state && this.workoutGpsDownload == 0) {
public boolean startWorkoutSync() {
synchronized (this) {
if (isSyncActive()) {
LOG.warn("Attempted to start workout sync while another sync is still active");
return false;
}
this.workoutSync = true;
}
LOG.debug("Set workout sync state to true");
return true;
}
public void stopWorkoutSync() {
LOG.debug("Set workout sync state to false");
this.workoutSync = false;
if (workoutGpsDownload != 0) {
this.syncQueue.remove((Integer) RecordedDataTypes.TYPE_GPS_TRACKS);
supportProvider.fetchRecodedDataFromQueue();
}
@@ -96,7 +127,7 @@ class HuaweiSyncState {
}
public void updateState(boolean needSync) {
if (!activitySync && !p2pSync && !workoutSync && workoutGpsDownload == 0) {
if (!isSyncActive()) {
if (supportProvider.getDevice().isBusy()) {
supportProvider.getDevice().unsetBusyTask();
supportProvider.getDevice().sendDeviceUpdateIntent(supportProvider.getContext());