Yeah X-Timestamp comes through the proxy in part for container sync, it's useful and weird, but there it is.
So the risk is using up inodes on a single file system? If you can get this going on more objects than your estimate there are disks in the cluster you could ruin some poor ops day.
Won't a replication pass clear them out once you get the attacking account cut off?
I tried to write a patch in the object server's DELETE method that would only create the new timestamp if the object was deleted already and the already deleted object's orig_timestamp was larger than the requests timestamp - but all the branching made it look ugly to me.
I'm sort of inclined to just say:
diff --git a/swift/obj/server.py b/swift/obj/server.py
index 4bbbb4e..f1f486e 100644
--- a/swift/obj/server.py
+++ b/swift/obj/server.py
@@ -996,7 +996,7 @@ class ObjectController(object): return HTTPPreconditionFailed( request=request, body='X-If-Delete-At and X-Delete-At do not match')
- orig_timestamp = disk_file.metadata.get('X-Timestamp')
+ orig_timestamp = int(disk_file.metadata.get('X-Timestamp', 0))
if disk_file.is_deleted() or disk_file.is_expired(): response_class = HTTPNotFound metadata = {
@@ -1007,7 +1007,7 @@ class ObjectController(object): self.delete_at_update('DELETE', old_delete_at, account, container, obj, request, device) disk_file.put_metadata(metadata, tombstone=True)
- disk_file.unlinkold(metadata['X-Timestamp'])
+ disk_file.unlinkold(max(int(metadata['X-Timestamp']), orig_timestamp)
if not orig_timestamp or \ orig_timestamp < request.headers['x-timestamp']: self.container_update(
Yeah X-Timestamp comes through the proxy in part for container sync, it's useful and weird, but there it is.
So the risk is using up inodes on a single file system? If you can get this going on more objects than your estimate there are disks in the cluster you could ruin some poor ops day.
Won't a replication pass clear them out once you get the attacking account cut off?
I tried to write a patch in the object server's DELETE method that would only create the new timestamp if the object was deleted already and the already deleted object's orig_timestamp was larger than the requests timestamp - but all the branching made it look ugly to me.
I'm sort of inclined to just say:
diff --git a/swift/ obj/server. py b/swift/ obj/server. py obj/server. py obj/server. py r(object) :
return HTTPPreconditio nFailed(
request= request,
body='X- If-Delete- At and X-Delete-At do not match') metadata. get('X- Timestamp' ) file.metadata. get('X- Timestamp' , 0)) is_deleted( ) or disk_file. is_expired( ):
response_ class = HTTPNotFound
metadata = { r(object) :
self. delete_ at_update( 'DELETE' , old_delete_at, account,
container, obj, request, device)
disk_ file.put_ metadata( metadata, tombstone=True) unlinkold( metadata[ 'X-Timestamp' ]) unlinkold( max(int( metadata[ 'X-Timestamp' ]), orig_timestamp)
orig_timestamp < request. headers[ 'x-timestamp' ]:
self. container_ update(
index 4bbbb4e..f1f486e 100644
--- a/swift/
+++ b/swift/
@@ -996,7 +996,7 @@ class ObjectControlle
- orig_timestamp = disk_file.
+ orig_timestamp = int(disk_
if disk_file.
@@ -1007,7 +1007,7 @@ class ObjectControlle
- disk_file.
+ disk_file.
if not orig_timestamp or \